数学题!
从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(" "); 58 } 59 } 60 return 0; 61 }