显然,恰好有
k
k
k个不相同的位置就意味着恰好有
n
−
k
n-k
n−k个位置的数是相同的,不妨令
k
=
n
−
k
k=n-k
k=n−k,求恰好有
k
k
k个位置相同且满足条件的方案数。
可以考虑这样一个容斥:令
s
[
i
]
s[i]
s[i]表示有因子
i
i
i的数的个数,那么可以得到
f
[
i
]
=
∑
i
∣
j
μ
(
j
i
)
(
s
[
j
]
k
)
(
⌊
m
j
⌋
−
1
)
s
[
j
]
−
k
(
⌊
m
j
⌋
)
n
−
s
[
j
]
f[i]=\sum_{i|j}\mu(\frac{j}{i}){s[j]\choose k}(\lfloor\frac{m}{j}\rfloor-1)^{s[j]-k}(\lfloor\frac{m}{j}\rfloor)^{n-s[j]}
f[i]=i∣j∑μ(ij)(ks[j])(⌊jm⌋−1)s[j]−k(⌊jm⌋)n−s[j]
式子的含义应该比较简单,考虑先用
s
[
j
]
s[j]
s[j]个含有因子
j
j
j的填满
k
k
k个相同的位置,那么剩下的
s
[
j
]
−
k
s[j]-k
s[j]−k个位置中每一个都有
⌊
m
j
⌋
−
1
\lfloor\frac{m}{j}\rfloor-1
⌊jm⌋−1种选择,剩下
n
−
s
[
j
]
n-s[j]
n−s[j]个位置中每一个都有
⌊
m
j
⌋
\lfloor\frac{m}{j}\rfloor
⌊jm⌋种选择。
求
s
s
s和
f
f
f都可以通过
O
(
m
log
m
)
O(m\log m)
O(mlogm)的时间复杂度来实现
时间复杂度:
O
(
m
log
m
)
O(m\log m)
O(mlogm)
反正这种题想怎么玩就怎么玩,快乐就行
代码
#include<bits/stdc++.h>usingnamespace std;template<typename T>voidchkmax(T &x, T y){x = x > y ? x : y;}template<typename T>voidchkmin(T &x, T y){x = x < y ? x : y;}template<typename T>voidread(T &x){
x =0;int f =1;char c =getchar();while(!isdigit(c)){if(c =='-') f =-1; c =getchar();}while(isdigit(c)) x = x *10+ c -'0', c =getchar(); x *= f;}constint N =300010, Mod =1e9+7;int a[N], f[N], s[N], p[N], mu[N], tx[N], ty[N], fl[N], fac[N], inv[N], Inv[N];voidadd(int&x,int y){x += y;if(x >= Mod) x -= Mod;}intC(int n,int m){return1ll* fac[n]* Inv[m]% Mod * Inv[n - m]% Mod;}intPow(int x,int y){if(y <0)return0;int ret =1;for(; y; y >>=1, x =1ll* x * x % Mod)if(y &1) ret =1ll* ret * x % Mod;return ret;}intmain(){int n, m, K;read(n),read(m),read(K); K = n - K;for(int i =1; i <= n; i++){int x;read(x); a[x]++;}for(int i = m; i; i--)for(int j = i; j <= m; j += i)
s[i]+= a[j];
fac[0]= fac[1]= inv[1]= Inv[0]= Inv[1]=1;for(int i =2; i <= n; i++){
inv[i]=1ll*(Mod - Mod / i)* inv[Mod % i]% Mod;
Inv[i]=1ll* Inv[i -1]* inv[i]% Mod;
fac[i]=1ll* fac[i -1]* i % Mod;}for(int i =1; i <= m; i++)
tx[i]=Pow(m / i -1, s[i]- K), ty[i]=Pow(m / i, n - s[i]);int len =0; mu[1]=1;for(int i =2; i <= m; i++){if(!fl[i]) p[++len]= i, mu[i]=-1;for(int j =1; j <= len && i * p[j]<= m; j++){int k = i * p[j]; fl[k]=1;if(i % p[j]==0){mu[k]=0;continue;}
mu[k]=-mu[i];}}for(int i =1; i <= m; i++)add(mu[i], Mod);for(int i =1; i <= m; i++)for(int j = i; j <= m; j += i)if(s[j]>= K)add(f[i],1ll* mu[j / i]*C(s[j], K)% Mod * tx[j]% Mod * ty[j]% Mod);for(int i =1; i <= m; i++) cout << f[i]<<' '; cout <<"\n";return0;}