[xdoj1227]Godv的数列(crt+lucas)

解题关键: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 }

 

posted @ 2017-08-25 18:58  Elpsywk  阅读(246)  评论(0编辑  收藏  举报