题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4675
题意:给一个大小为N的数列a[i],然后一个数M以及一个数K,要你求得一个数列b[i],其中b[i]有K个数与a[i]中的不相同,使得gcd(b[i])=j。对于每个 j ,求出满足的b[i]的个数。。
首先我们统计数列a[i]每个数的个数,假设现在求gcd(b[i])=j,那么可以在t=M/j的时间内求出 j 的倍数的个数cnt。那么就相当于在cnt个中选择N-K个不变C(cnt,N-K),在剩下的 j 的倍数中有(t-1)^(cnt-t)种,非 j 的倍数中有t^(N-cnt)种,那么就是C(cnt,N-K)*(t-1)^(cnt-t)*t^(N-cnt)。这里求出的是gcd(b[i])为 j 的倍数的情况,还要减去2*j,3*j...的数目,因此 j 从M开始倒推就可以了,减去ans[2*j],ans[3*j]...
//STATUS:C++_AC_1796MS_6144KB
#include <functional>
#include <algorithm>
#include <iostream>
//#include <ext/rope>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,102400000")
//using namespace __gnu_cxx;
//define
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1.0)
//typedef
typedef __int64 LL;
typedef unsigned __int64 ULL;
//const
const int N=;
const int INF=0x3f3f3f3f;
const LL MOD=,STA=;
const LL LNF=1LL<<;
const double EPS=1e-;
const double OO=1e50;
const int dx[]={-,,,};
const int dy[]={,,,-};
const int day[]={,,,,,,,,,,,,};
//Daily Use ...
inline int sign(double x){return (x>EPS)-(x<-EPS);}
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
//End LL C[N],ans[N];
int cnt[N];
int n,m,k; void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
if(!b){d=a;x=;y=;}
else {exgcd(b,a%b,d,y,x);y-=x*(a/b);}
} LL inv(LL a)
{
LL d,x,y;
exgcd(a,MOD,d,x,y);
return (x+MOD)%MOD;
} LL mulpow(LL n,int m)
{
LL ret=;
for(;m;m>>=){
if(m&)ret=(ret*n)%MOD;
n=(n*n)%MOD;
}
return ret;
} int main(){
// freopen("in.txt","r",stdin);
int i,j,a,tot,t,p;
LL s;
while(~scanf("%d%d%d",&n,&m,&k))
{
C[t=n-k]=;
for(i=t+;i<=n;i++){
C[i]=(i*C[i-]%MOD*inv(i-t))%MOD;
}
mem(cnt,);
for(i=;i<n;i++){
scanf("%d",&a);
cnt[a]++;
}
for(i=m;i>=;i--){
tot=cnt[i];s=;
for(j=i+i;j<=m;j+=i){
tot+=cnt[j];
s=(s+ans[j])%MOD;
}
if(t>tot)ans[i]=;
else {
p=m/i;
ans[i]=(C[tot]*mulpow(p-,tot-t)%MOD*mulpow(p,n-tot))%MOD;
ans[i]=(ans[i]-s+MOD)%MOD;
}
} printf("%I64d",ans[]);
for(i=;i<=m;i++)
printf(" %I64d",ans[i]);
putchar('\n');
}
return ;
}