解题关键:1001=7*11*13,模数非常小,直接暴力lucas。递归次数几乎为很小的常数。最后用中国剩余定理组合一下即可。
模数很小时,一定记住lucas定理的作用
http://acm.xidian.edu.cn/problem.php?id=1227
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+7; 5 const int mod=1001; 6 inline int read(){ 7 char k=0;char ls;ls=getchar();for(;ls<‘0‘||ls>‘9‘;k=ls,ls=getchar()); 8 int x=0;for(;ls>=‘0‘&&ls<=‘9‘;ls=getchar())x=(x<<3)+(x<<1)+ls-‘0‘; 9 if(k==‘-‘)x=0-x;return x; 10 } 11 int a[maxn],fac[5][maxn],inv[5][maxn]; 12 ll mod_pow(ll x,ll n,ll p){ 13 ll res=1; 14 while(n){ 15 if(n&1) res=res*x%p; 16 x=x*x%p; 17 n>>=1; 18 } 19 return res; 20 } 21 ll comb(ll n,ll m,ll p){ 22 if(n==m) return 1; 23 if(n<m) return 0; 24 if(m>n-m) m=n-m; 25 26 ll tn=1,tm=1; 27 while(m){ 28 tn=tn*n%p; 29 tm=tm*m%p; 30 n--,m--; 31 } 32 return tn*mod_pow(tm,p-2,p)%p; 33 } 34 ll lucas(ll n,ll m,ll p){ 35 ll res=1; 36 while(m){ 37 res=res*comb(n%p,m%p,p)%p; 38 n/=p; 39 m/=p; 40 } 41 return res; 42 } 43 int main(){ 44 int t,n; 45 t=read(); 46 while(t--){ 47 n=read(); 48 for(int i=1;i<=n;i++) a[i]=read()%1001; 49 int ans=0,t1,t2,tans,t3; 50 for(int i=1;i<=n;i++){ 51 t3=lucas(n-1,i-1,13); 52 t2=lucas(n-1,i-1,11); 53 t1=lucas(n-1,i-1,7); 54 tans=(715*t1+364*t2+924*t3)%1001; 55 ans=(ans+tans*a[i])%1001; 56 } 57 printf("%d\n",ans); 58 } 59 return 0; 60 }
时间: 2024-10-10 06:34:42