转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目:给出n个数,b1,b2,b3……bn,构造n个数,a1,a2,……an(ai>1),使得a1*a2*a3……an=b1*b2……bn;
http://acm.hdu.edu.cn/showproblem.php?pid=4390
首先是将所有 的b进行素因子分解,则a和b的因子是完全一致的。
剩下的便是将所有b的因子,分给a
我们考虑某个素因子pi,如果有ci个,便成了子问题将ci个相同的物品放入到n个不同的容器中,种数为多少
但是要求ai>1,也就是容器不能为空,这是个问题。
我们考虑的是什么的情况,然后减去假设有一个确定是空的情况,发现可以用容斥原理解决
我们假设f[i]表示有i个容器的结果,c(n,i)*f[i]
将m个物品放到到不同的n个容器中,结果为c(n+m-1,n-1)
#include<iostream>
#include<cstdio>
#include <queue>
#include<cstring>
#include<algorithm>
#include<vector>
#define pb(a) push_back(a)
#define MOD 1000000007
#define LL long long
using namespace std;
int n;
LL c[505][505];
vector<int>p;
void fuck(int num)
{
for(int i=2;i*i<=num;i++)
{
while(num%i==0)
{
num/=i;
p.pb(i);
}
}
if(num>1) p.pb(num);
}
void Init()
{
for(int i=0;i<=500;i++)
{
c[i][0]=c[i][i]=1;
for(int j=1;j<i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;
}
}
LL get(int n,int m)
{
return c[m+n-1][n-1];
}
LL slove()
{
int a[1005]={1},cnt=0;
sort(p.begin(),p.end());
for(int i=1;i<p.size();i++)
{
if(p[i]!=p[i-1]) a[++cnt]=1;
else a[cnt]++;
}
LL ans=1;
for(int i=0;i<=cnt;i++) ans=(ans*get(n,a[i]))%MOD;
//cout<<ans<<endl;
for(int i=1;i<n;i++)
{
LL tmp=c[n][i];
for(int j=0;j<=cnt;j++)
{
tmp=(tmp*get(n-i,a[j]))%MOD;
}
if(i&1) ans=((ans-tmp)%MOD+MOD)%MOD;
else ans=(ans+tmp)%MOD;
}
return ans;
}
int main()
{
Init();
while(scanf("%d",&n)!=EOF)
{
p.clear();
for(int i=0;i<n;i++)
{
int k;
scanf("%d",&k);
fuck(k);
}
printf("%I64d\n",slove());
}
return 0;
}