Number Sequence
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 790 Accepted Submission(s): 331
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
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
题意:
求一个数列 a1,a2,..an,使a 1*a 2*...*a n=b 1*b 2*…*b n ,其中ai>1;
思路:
刚开始没什么思路,在网上找了很久,发现很多博客都是千篇一律的,后来总结了一下。。
1.先对每个bi跟姐质因数,用map保存每个因子出现的次数,此时ai*a2*...an的质因子为map保存的;
2.现在的问题就是将n个相同的数放进m个盒子里,假设盒子可为空,则所有情况为C(n+m-1,n-1),然后,对map里保存的因子个数逐个代入计算,
再应用乘法原理就可以求出盒子可为空时所有的情况。
3.题目要求盒子不可为空,这就要用到数学归纳法了:
f[i]-放入i个数能够为空的种数,g[i]-放入i个数不能为空的种数:
f[1]=g[1]
f[2]=g[2]+C(2,1)*g[1],
f[3]=g[3]+C(3,1)*g[2]+C(3,2)*g[1],
......
g[n]=f[n]-C(n,1)*f[n-1]+C(n,2)*f[n-2]-...
依次计算有i个盒子为空的组合数,应用容斥原理:-g[1]+g[2]-g[3]+g[4]....;
My Code:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<string> #include<algorithm> #include<cstdlib> #include<set> #include<queue> #include<stack> #include<vector> #include<map> #define N 100010 #define mod 1000000007 #define lson l,mid,idx<<1 #define rson mid+1,r,idx<<1|1 #define lc idx<<1 #define rc idx<<1|1 const double EPS = 1e-11; const double PI = acos(-1.0); const double E=2.718281828; typedef long long ll; const int INF=1000010; using namespace std; int C[1001][45];///组合数 map<int,int>mp; void init() { for(int i=0; i<=1000; i++) C[i][0]=1;///i个选0个为1; for(int i=1; i<=1000; i++) for(int j=1; j<=42; j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;///c(n,k)=c(n-1,k)+c(n-1,k-1),可以自己证明 } void Fenjie(int n)///分解质因数 { for(int i=2; i*i<=n; i++) { if(n%i==0) { while(n%i==0) { mp[i]++; n/=i; } } if(n==1) break; } if(n>1) mp[n]++; } int main() { init(); int n; while(cin>>n) { mp.clear(); int b; for(int i=0; i<n; i++) { scanf("%d",&b); Fenjie(b); } ll ans=0; for(int i=0; i<n; i++)///容斥原理 { ll tem=C[n][i]; map<int,int>::iterator it; for(it=mp.begin(); it!=mp.end(); it++)///计算有i个盒子为空的组合数 { int t=it->second+n-i-1; tem*=C[t][n-i-1]; tem%=mod; } if(i%2) ans-=tem,ans+=mod; else ans+=tem; ans%=mod; } cout<<ans%mod<<endl; } return 0; }