HDU 4390 Number Sequence(容斥原理)

Number Sequence

Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 822    Accepted Submission(s): 339


Problem Description
Given a number sequence b1,b2…bn.
Please count how many number sequences a1,a2,...,an satisfy the condition that a1*a2*...*an=b1*b2*…*bn (ai>1).
 
Input
The input consists of multiple test cases. 
For each test case, the first line contains an integer n(1<=n<=20). The second line contains n integers which indicate b1, b2,...,bn(1<bi<=1000000, b1*b2*…*bn<=1025).
 
Output
For each test case, please print the answer module 1e9 + 7.
 
Sample Input
2
3 4
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<string>
 6 #include<vector>
 7 #include<queue>
 8 #include<cmath>
 9 using namespace std;
10 
11 #define mod 1000000007
12 #define LL long long
13 int prim[800000], f[1000000];
14 int c[505][505];
15 vector<int> V;
16 int len = 0, n;
17 /**首先是将所有 的b进行素因子分解,则a和b的因子是完全一致的。
18 剩下的便是将所有b的因子,分给a
19 我们考虑某个素因子pi,如果有ci个,便成了子问题将ci个相同的物品放入到n个不同的容器中,种数为多少
20 但是要求ai>1,也就是容器不能为空,这是个问题。
21 我们考虑的是什么的情况,然后减去假设有一个确定是空的情况,发现可以用容斥原理解决
22 我们假设f[i]表示有i个容器的结果,c(n,i)*f[i]
23 将m个物品放到到不同的n个容器中,结果为c(n+m-1,n-1)**/
24 void init(int n) {
25     prim[0] = 2; len = 1;
26     for(int i = 3; i < n; i += 2) if(!f[i]) {
27         prim[len++] = i;
28         for(int j = 3 * i; j < n; j += 2*i) f[j] = true;
29     }
30     for(int i = 0; i <= 500; i++){
31         c[i][0] = c[i][i] = 1;
32         for(int j = 1; j < i; j++)
33             c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mod;
34     }
35 }
36 void resolve(int d){
37     for(int i = 0; prim[i] <= d; i++){
38         while(d % prim[i] == 0){ V.push_back(prim[i]); d /= prim[i]; }
39     }
40     //for(int i = 2; i*i <= d; i++){
41        // while(d % i == 0){ d /= i; V.push_back(i);}
42     //}
43     if(d > 1)V.push_back(d);
44 }
45 LL get(int n, int m){
46     return c[n+m-1][n-1];
47 }
48 LL solve(){
49     sort(V.begin(), V.end());
50     int a[1020] = {1}, l = 0;
51     for(int i = 1; i < V.size(); i++){
52         if(V[i] != V[i-1])a[++l] = 1;
53         else a[l] ++;
54     }
55     LL ans = 1;
56     for(int i = 0; i <= l; i++)ans = (ans * get(n,a[i])) % mod;
57     for(int i = 1; i < n; i++){
58         LL t = c[n][i];//????
59         for(int j = 0; j <= l; j++){
60             //n-i相当于有i个空位
61             t = (t * get(n-i, a[j])) % mod;
62         }
63         if( i&1 )ans = ((ans - t) % mod + mod) % mod;
64         else ans = (ans + t) % mod;
65     }
66     return ans;
67 }
68 int main()
69 {
70     int i, d;
71     init(1000000);
72     while(~scanf("%d", &n)){
73         V.clear();//初始化
74         for(i = 0; i < n; i++){
75             scanf("%d", &d);
76             resolve(d);
77         }
78         cout<<solve()<<endl;
79     }
80     return 0;
81 }
View Code

 

posted @ 2014-04-28 16:26  SStep  阅读(228)  评论(0编辑  收藏  举报