hdu 4390 Number Sequence 容斥原理
将每一个数分解质因数,得到每个质因数出现的次数(和质数本身没有关系),然后就要用到容斥原理了,
也就是将每个质数出现的次数放到n个容器中去,这里要注意下1的情况也就是某个容器里面没有放数。
这样结果=总的方案数-有一个容器没放数+有2个容器没有放数……
将m个数放入n个容器的方法数有C(n+m-1,n-1)!
代码如下:
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cmath> 6 #include<cstring> 7 #include<vector> 8 #define ll __int64 9 #define pi acos(-1.0) 10 #define SIZE 1024 11 using namespace std; 12 const int mod =1000000007; 13 int n; 14 ll c[101][101]; 15 vector<int>p; 16 void init() 17 { 18 int i,j; 19 for(i=0;i<=100;i++){ 20 c[i][0]=c[i][i]=1; 21 for(j=1;j<i;j++) 22 c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod; 23 } 24 } 25 ll get(int n,int m) 26 { 27 return c[n+m-1][n-1]; 28 } 29 void fen(int num) 30 { 31 int i; 32 for(i=2;i*i<=num;i++){ 33 while(num%i==0){ 34 p.push_back(i); 35 num/=i; 36 } 37 } 38 if(num>1) p.push_back(num); 39 } 40 ll solve() 41 { 42 int i,j,cnt,an[505]={1}; 43 sort(p.begin(),p.end()); 44 cnt=0; 45 for(i=1;i<p.size();i++){ 46 if(p[i]!=p[i-1]) an[++cnt]=1; 47 else an[cnt]++; 48 } 49 ll ans=1; 50 for(i=0;i<=cnt;i++) ans=(ans*get(n,an[i]))%mod; 51 for(i=1;i<n;i++){ 52 ll temp=c[n][i]; 53 for(j=0;j<=cnt;j++){ 54 temp=(temp*get(n-i,an[j]))%mod; 55 } 56 if(i&1) ans=((ans-temp)%mod+mod)%mod; 57 else ans=(ans+temp)%mod; 58 } 59 return ans%mod; 60 } 61 int main(){ 62 int i,j,t; 63 init(); 64 while(cin>>n&&n){ 65 p.clear(); 66 for(i=0;i<n;i++){ 67 cin>>t; 68 fen(t); 69 } 70 printf("%I64d\n",solve()); 71 } 72 return 0; 73 }