這裏就不用,還是寫的習慣些
直接計算一個方案是十分不方便的
所以考慮容斥
設表示的方案數
設中有個數是的倍數
那麼有
表示有個數是必須修改的,每個有種數選擇
那麼還剩個數必須要修改,我們可將其寫爲,這樣就是等價於要選個數出來
表示將這個數修改個數,每個數因爲自己本身是的一個倍數,所以只有種選擇
設表示的方案數
然後可以考慮莫比烏斯反演
顯然有
則根據莫比烏斯反演,有
當然,莫比烏斯反演什麼的是不可能莫比烏斯反演的
直接容斥就可以啦
從大到小枚舉,直接計算即可
/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年08月23日 星期五 08時14分25秒
*******************************/
#include <cstdio>
#include <fstream>
#define ll long long
using namespace std;
const int maxn = 300005;
const int mod = 1000000007;
//{{{cin
struct IO{
template<typename T>
IO & operator>>(T&res){
res=0;
bool flag=false;
char ch;
while((ch=getchar())>'9'||ch<'0') flag|=ch=='-';
while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
if (flag) res=~res+1;
return *this;
}
}cin;
//}}}
int n,m,k;
int a[maxn],num[maxn];
ll fac[maxn],inv[maxn],f[maxn];
//{{{ksm
int ksm (int a,int b)
{
a%=mod;
int s=1;
for (;b;b>>=1,a=1ll*a*a%mod)
if (b&1) s=1ll*s*a%mod;
return s;
}
//}}}
inline ll C (int n,int m)
{
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
cin>>n>>m>>k;
fac[0]=fac[1]=inv[0]=inv[1]=1;
for (int i=1;i<=n;++i) cin>>a[i],++num[a[i]];
for (int i=2;i<=n;++i) fac[i]=1ll*fac[i-1]*i%mod;
for (int i=2;i<=n;++i) inv[i]=(-mod/i*inv[mod%i]%mod+mod)%mod;
for (int i=2;i<=n;++i) inv[i]=1ll*inv[i]*inv[i-1]%mod;
for (int i=m;i>=1;--i){
int cnt=0;
for (int j=i;j<=m;j+=i) cnt+=num[j];
if (cnt-n+k<0) f[i]=0;
else f[i]=C(cnt,n-k)*ksm(m/i-1,cnt-n+k)%mod*ksm(m/i,n-cnt)%mod;
for (int j=i<<1;j<=m;j+=i) f[i]=1ll*(f[i]-f[j]+mod)%mod;
}
for (int i=1;i<=m;++i) printf("%lld ",f[i]);
return 0;
}
如有哪裏講得不是很明白或是有錯誤,歡迎指正
如您喜歡的話不妨點個贊收藏一下吧