题目大意:
给定一个长度为n的序列a以及值域[1,m],要求构造b满足(b_i)属于[1,m]且(b_i!=a_i)的关系恰有k对
没用莫反做
一开始想的很复杂,后来发现求i的答案不好求,改成求i的倍数的
也就是单独求gcd=i的很难,但如果改为i的倍数,就可以只考虑所选数是不是i的倍数。
有k次机会来改变a序列,如果某个数不是i的倍数,就必须给他一个机会,不然的话就可改可不改。
然后柿子就显然了。
#include<cstdio>
#include<iostream>
using namespace std;
const int N=3e5+7,maxn=3e5,mod=1e9+7;
inline int read() {
int x=0;char c=getchar();
for(;c<'0'||c>'9';c=getchar());
for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-48;
return x;
}
int js[N],inv[N],c[N],f[N],g[N];
inline int C(int n,int m) {
if(m<0||m>n) return 0;
return 1ll*js[n]*inv[m]%mod*inv[n-m]%mod;
}
inline int qpow(int a,int b,int c=1) {
for(;b;b>>=1,a=1ll*a*a%mod) if(b&1) c=1ll*c*a%mod;
return c;
}
inline void moded(int &x) {
if(x>=mod) x-=mod;if(x<0) x+=mod;
}
signed main() {
js[0]=inv[0]=1;
for(int i=1;i<=maxn;++i) js[i]=1ll*js[i-1]*i%mod;
inv[maxn]=qpow(js[maxn],mod-2);
for(int i=maxn-1;i;--i) inv[i]=1ll*inv[i+1]*(i+1)%mod;
int n,m,k;
while(scanf("%d%d%d",&n,&m,&k)!=EOF) {
for(int i=1;i<=m;++i) c[i]=0;
for(int i=1;i<=n;++i) c[read()]++;
for(int i=m;i;--i) {
int tt=0;
for(int j=1;i*j<=m;++j) tt+=c[i*j];f[i]=0;
if(n-tt>k) continue;
f[i]=1ll*C(tt,k-(n-tt))*qpow(m/i-1,k-(n-tt))%mod*qpow(m/i,n-tt)%mod;
}
for(int i=m;i;--i) for(int j=2;j*i<=m;++j) moded(f[i]=f[i]-f[i*j]);
for(int i=1;i<=m;++i) printf("%d ",f[i]);
puts("");
}
return 0;
}