HDU 4390 Number Sequence 容斥原理

Number Sequence

Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Problem Description
Given a number sequence b 1,b 2…b n. Please count how many number sequences a 1,a 2,...,a n satisfy the condition that a 1*a 2*...*a n=b 1*b 2*…*b n (a i>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 b 1, b 2,...,b n(1<b i<=1000000, b 1*b 2*…*b n<=10 25).
 
Output
For each test case, please print the answer module 1e9 + 7.
 
Sample Input
2 3 4
 
Sample Output
4
Hint
For the sample input, P=3*4=12. Here are the number sequences that satisfy the condition:
2 6
3 4
4 3
6 2
 
Source
2012 Multi-University Training Contest 10
 
 

将每一个数分解质因数,得到每个质因数出现的次数(和质数本身没有关系),然后就要用到容斥原理了,

也就是将每个质数出现的次数放到n个容器中去,这里要注意下1的情况也就是某个容器里面没有放数。

这样结果=总的方案数-有一个容器没放数+有2个容器没有放数……

将m个数放入n个容器的方法数有C(n+m-1,n-1) 。

#include <iostream>
#include <stdio.h>
#include <queue>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <set>
#include <algorithm>
#include <map>
#include <stack>
#include <math.h>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std ;
typedef long long LL ;
const int M_P=1008 ;
const LL Mod=1000000007 ;
bool isprime[M_P+8] ;
int prime[M_P] ,id;
map<int ,int>my_hash ;
map<int ,int>::iterator p ;
void make_prime(){
    id=0 ;
    memset(isprime,0,sizeof(isprime)) ;
    for(int i=2;i<=M_P;i++){
        if(!isprime[i])
             prime[++id]=i ;
        for(int j=1 ;j<=id&&i*prime[j]<=M_P;j++){
             isprime[i*prime[j]]=1 ;
             if(i%prime[j]==0)
                  break  ;
        }
    }
}
LL C[258][258] ;
void get_C(){
    C[1][0]=C[1][1]=1 ;
    for(int i=2;i<=250;i++){
         C[i][0]=C[i][i]=1 ;
         for(int j=1;j<i;j++){
            C[i][j]=C[i-1][j-1]+C[i-1][j] ;
            if(C[i][j]>=Mod)
                C[i][j]%=Mod ;
         }
    }
}
void gao(int N){
   for(int i=1;i<=id&&prime[i]*prime[i]<=N;i++){
       if(N%prime[i]==0){
          while(N%prime[i]==0){
                my_hash[prime[i]]++ ;
                N/=prime[i] ;
          }
       }
       if(N==1)
           break  ;
   }
   if(N!=1)
       my_hash[N]++ ;
}
vector<int>vec ;
int N ;
LL Sum(){
    LL ans=1 ;
    for(int k=0;k<vec.size();k++){
        ans*=C[vec[k]+N-1][N-1] ;
        if(ans>=Mod)
            ans%=Mod ;
    }
    for(int i=1;i<=N;i++){
        LL sum=C[N][i] ;
        for(int k=0;k<vec.size();k++){
            int m=N-i ;
            sum*=C[vec[k]+m-1][m-1] ;
            if(sum>=Mod)
                sum%=Mod  ;
        }
        if(i&1)
            ans-=sum  ;
        else
            ans+=sum  ;
        ans=(ans%Mod+Mod)%Mod ;
    }
    return ans ;
}
int main(){
   make_prime() ;
   get_C() ;
   int M  ;
   while(scanf("%d",&N)!=EOF){
       my_hash.clear() ;
       vec.clear() ;
       for(int i=1;i<=N;i++){
            scanf("%d",&M) ;
            gao(M) ;
       }
       for(p=my_hash.begin();p!=my_hash.end();p++)
           vec.push_back(p->second) ;
       cout<<Sum()<<endl;
   }
   return 0 ;
}

 

你可能感兴趣的:(HDU 4390 Number Sequence 容斥原理)