hdu 4675 GCD of Sequence

数学题!

从M到1计算,在计算i的时候,算出原序列是i的倍数的个数cnt;

也就是将cnt个数中的cnt-(n-k)个数变掉,n-cnt个数变为i的倍数。

且i的倍数为t=m/i;

则符合的数为:c[cnt][n-k]*t^(n-cnt)*(t-1)*(cnt-(n-k)).

这样得到的是所有i的倍数,还要减去2*i,3*i……

代码如下:

 

 1 #include<stdio.h>
 2 #include<cstring>
 3 #define M 1000000007
 4 #define MM 300001
 5 #define ll __int64
 6 #define I(x) scanf("%d",&x)
 7 int a[MM],num[MM];
 8 ll c[MM],an[MM],sum;
 9 ll pows(ll a,ll b)
10 {
11     ll ans=1;
12     while(b){
13         if(b&1) ans=(ans*a)%M;
14         b>>=1;
15         a=(a*a)%M;
16     }
17     return ans;
18 }
19 ll inv(ll a,ll m)
20 {
21     if(a == 1)return 1;
22     return inv(m%a,m)*(m-m/a)%m;
23 }
24 int main()
25 {
26     int n,m,k,i,j,cnt,t;
27     while(scanf("%d%d%d",&n,&m,&k)!=EOF){
28         memset(num,0,sizeof(num));
29         for(i=0;i<n;i++){
30             I(a[i]);
31             num[a[i]]++;
32         }
33         c[n-k]=1;
34         for(i=n-k+1;i<=n;i++) c[i]=c[i-1]*i%M*inv(i-(n-k),M)%M;
35         for(i=m;i>=1;i--){
36             cnt=0;sum=0;
37             for(j=1;i*j<=m;j++){
38                 cnt+=num[i*j];
39                 if(j>1) sum=(sum+an[i*j])%M;
40             }
41             t=m/i;
42             if(t==1){
43                 if(cnt==n-k) an[i]=1;
44                 else an[i]=0;
45                 continue;
46             }
47             if(cnt<n-k){
48                 an[i]=0;
49                 continue;
50             }
51             an[i]=c[cnt]*pows(t,n-cnt)%M*pows(t-1,cnt-(n-k))%M;
52             an[i]=((an[i]-sum)%M+M)%M;
53         }
54         for(i=1;i<=m;i++){
55             printf("%I64d",an[i]);
56             if(i<=m-1) printf(" ");
57             else printf("\n");
58         }
59     }
60     return 0;
61 }
View Code

 

 

 

posted @ 2013-08-14 16:30  _随心所欲_  阅读(220)  评论(0编辑  收藏  举报