【BZOJ 4305】 4305: 数列的GCD (数论)
4305: 数列的GCD
Description
给出一个长度为N的数列{a[n]},1<=a[i]<=M(1<=i<=N)。现在问题是,对于1到M的每个整数d,有多少个不同的数列b[1], b[2], ..., b[N],满足:(1)1<=b[i]<=M(1<=i<=N);(2)gcd(b[1], b[2], ..., b[N])=d;(3)恰好有K个位置i使得a[i]<>b[i](1<=i<=N)注:gcd(x1,x2,...,xn)为x1, x2, ..., xn的最大公约数。输出答案对1,000,000,007取模的值。Input
第一行包含3个整数,N,M,K。第二行包含N个整数:a[1], a[2], ..., a[N]。Output
输出M个整数到一行,第i个整数为当d=i时满足条件的不同数列{b[n]}的数目mod 1,000,000,007的值。Sample Input
3 3 3
3 3 3Sample Output
7 1 0HINT
当d=1,{b[n]}可以为:(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2), (2, 1, 1), (2, 1, 2), (2, 2, 1)。
当d=2,{b[n]}可以为:(2, 2, 2)。
当d=3,因为{b[n]}必须要有k个数与{a[n]}不同,所以{b[n]}不能为(3, 3, 3),满足条件的一个都没有。
对于100%的数据,1<=N,M<=300000, 1<=K<=N, 1<=a[i]<=M。Source
【分析】
smg,怎么说是容斥的。。。
【其实好像不是。。很难??
搞那么久我竟然for了一遍求cnt,然后就n^2极慢。。
【均摊log看过很多次,懂得。。。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Mod 1000000007 8 #define Maxn 300010 9 #define LL long long 10 11 int a[Maxn]; 12 LL p[Maxn],ans[Maxn]; 13 14 LL qpow(LL a,int b) 15 { 16 LL ans=1; 17 while(b) 18 { 19 if(b&1) ans=(ans*a)%Mod; 20 a=(a*a)%Mod; 21 b>>=1; 22 } 23 return ans; 24 } 25 26 LL get_c(int m,int n) 27 { 28 LL as=p[n]; 29 as=as*qpow(p[m],Mod-2)%Mod; 30 as=as*qpow(p[n-m],Mod-2)%Mod; 31 return as; 32 } 33 34 int cnt[Maxn],cc[Maxn]; 35 36 int main() 37 { 38 int n,m,k; 39 scanf("%d%d%d",&n,&m,&k); 40 k=n-k; 41 memset(cnt,0,sizeof(cnt)); 42 memset(cc,0,sizeof(cc)); 43 for(int i=1;i<=n;i++) 44 { 45 scanf("%d",&a[i]); 46 cc[a[i]]++; 47 } 48 for(int i=m;i>=1;i--) 49 { 50 for(int j=i;j<=m;j+=i) cnt[i]+=cc[j]; 51 } 52 p[0]=1; 53 for(LL i=1;i<=n;i++) p[i]=(p[i-1]*i)%Mod; 54 for(int i=m;i>=1;i--) 55 { 56 if(cnt[i]<k) ans[i]=0; 57 else 58 { 59 ans[i]=get_c(k,cnt[i])*qpow(m/i-1,cnt[i]-k)%Mod*qpow(m/i,n-cnt[i])%Mod; 60 for(int j=2;j<=m/i;j++) ans[i]=(ans[i]+Mod-ans[i*j])%Mod; 61 } 62 } 63 for(int i=1;i<m;i++) printf("%lld ",ans[i]); 64 printf("%lld\n",ans[m]); 65 // printf("\n"); 66 return 0; 67 }
2017-03-14 22:14:32