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
",solve());
71     }
72     return 0;
73 }
View Code
原文地址:https://www.cnblogs.com/xin-hua/p/3229345.html