Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 46 Accepted Submission(s): 14
比赛时候想到了做法,但是错估了复杂度,一直没写出来,结束后才搞完、
其实就是从M算到1.
假如现在算i. 那么找到i ~ M中i的倍数。
看原序列中有多少个是i的倍数,设为cnt.
因为最终假如gcd是i的话,所有数都必须是i的倍数。
那就相当于在cnt个中,要把cnt-(N-K)个变掉,其余的(N-cnt)个要变成i的倍数。
i的倍数为t = M/i 个。
那么符合的数有C[cnt][N-K]* (t-1)^(cnt-(N-K)) * t^(N-cnt)
这个算出来的是gcd是i的倍数的情况。
减掉gcd是2i,3i....这样的就行了
1 /* ********************************************** 2 Author : kuangbin 3 Created Time: 2013/8/13 16:39:35 4 File Name : F:\2013ACM练习\2013多校7\1010.cpp 5 *********************************************** */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 using namespace std; 19 20 const int MOD = 1e9+7; 21 long long pow_m(long long a,long long n) 22 { 23 long long ret = 1; 24 long long tmp = a%MOD; 25 while(n) 26 { 27 if(n&1) 28 { 29 ret *= tmp; 30 ret %= MOD; 31 } 32 tmp *= tmp; 33 tmp %= MOD; 34 n >>= 1; 35 } 36 return ret; 37 } 38 long long C[300010]; 39 //求ax = 1( mod m) 的x值,就是逆元(0<a<m) 40 long long inv(long long a,long long m) 41 { 42 if(a == 1)return 1; 43 return inv(m%a,m)*(m-m/a)%m; 44 } 45 long long ans[300010]; 46 int a[300010]; 47 int num[300010]; 48 int b[300010]; 49 int main() 50 { 51 //freopen("in.txt","r",stdin); 52 //freopen("out.txt","w",stdout); 53 int N,M,K; 54 while(scanf("%d%d%d",&N,&M,&K) == 3) 55 { 56 memset(num,0,sizeof(num)); 57 for(int i = 1;i <= N;i++) 58 { 59 scanf("%d",&a[i]); 60 num[a[i]]++; 61 } 62 C[N-K] = 1; 63 for(int i = N-K+1;i <= N;i++) 64 { 65 C[i] = C[i-1]*i%MOD*inv(i-(N-K),MOD)%MOD; 66 } 67 for(int i = M;i>= 1;i--) 68 { 69 int cnt = 0; 70 long long ss = 0; 71 for(int j = 1; j*i <= M;j++) 72 { 73 cnt += num[i*j]; 74 if(j > 1)ss = (ss + ans[i*j])%MOD; 75 } 76 int t = M/i; 77 if(t == 1) 78 { 79 if(cnt == N-K)ans[i] = 1; 80 else ans[i] = 0; 81 continue; 82 } 83 84 if(cnt < N-K) 85 { 86 ans[i] = 0; 87 continue; 88 } 89 long long tmp = 1; 90 //在cnt个中选N-K个为相同的 91 tmp =(tmp*C[cnt])%MOD; 92 //其余的cnt-(N-K)个有t-1个选择 93 tmp = ( tmp * pow_m(t-1,cnt-(N-K)) )%MOD; 94 //其余N-cnt个本来就不相同的,有t个选择 95 tmp = (tmp * pow_m(t,N-cnt)); 96 ans[i] = (tmp - ss + MOD)%MOD; 97 98 99 } 100 for(int i = 1;i <= M;i++) 101 { 102 printf("%I64d",ans[i]); 103 if(i < M)printf(" "); 104 else printf("\n"); 105 } 106 107 } 108 return 0; 109 }