zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    vim中自动添加文件的作者、时间信息、版本等
    linux shell ipaddress
    java ant学习
    ganglia rpm安装
    深入分析 Java 中的中文编码问题
    javaIO调优
    超强的vim设置
    linux中core文件的生成和配置
    C和C++ 语言动态内存分配
    Linux的常用命令
  • 原文地址:https://www.cnblogs.com/qiu520/p/3696637.html
Copyright © 2011-2022 走看看