HDU 4390
题意:
大概就是这样,不翻译了:
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,bi>1).
思路:
我们可以确定一件事:等号两边由相同数量的质因子组成。
如果
ai
可以等于1,答案就是把这些质因子分配进n个位置的方案数。
设左边的数字共由x个质因子组成,其中第i个质因子出现
mi
次。
把m个相同小球放进n个不同盒子(盒子可以为空)中的方案数是
Cn−1m+n−1
。
那么把
mi
个相同质因子放进n个不同位置上的方案数是
Cn−1mi+n−1
,最后答案就是
∏xi=1Cn−1mi+n−1
.
但这并不是我们想要的答案,因为我们不允许某个位置为空(即存在
ai=1
),所以我们要减去一些某些位置为空的方案。
因为至少有一个位置为空与至少有两个位置为空存在重复情况等,减的方法是容斥原理。
ans=∏xi=1Cn−1mi+n−1−C1n∏xi=1Cn−2mi+n−2+C2n∏xi=1Cn−3mi+n−3−...Cn−1n∏xi=1C0mi
.
(答案 = 所有可能 - 一个为空 + 两个为空 - 三个为空 +…)
代码:
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const int maxn = 1005 ;
const int mod = 1e9 + 7 ;
lint C[505][505];
lint b[25] ;
map<int , int>m ;
int n ;
void init(){
cls( C ) ;
C[0][0] = 1 ;
for( int i = 1 ; i <= 500 ; i++ ){
C[i][0] = 1 ;
for( int j = 1 ; j <= i ; j++ ){
C[i][j] = C[i-1][j] + C[i-1][j-1] ;
if( C[i][j] > mod ) C[i][j] -= mod ;
}
}
}
lint work(){
for( int i = 1 ; i <= n ; i++ ){
for( int j = 2 ; j * j <= b[i] ; j++ ){
while( b[i] % j == 0 ) {
m[j] ++ ;
b[i] /= j ;
}
}
if( b[i] > 1 ) m[b[i]] ++ ;
}
map<int,int>::iterator it ;
lint ans = 1 ;
for( it = m.begin() ; it != m.end() ; it++ ){
int num = it->second ;
ans = ( ans * C[ num + n - 1 ][ n - 1 ] ) % mod ;
}
for( int i = 1 ; i < n ; i++ ){
lint val = C[n][i] ;
for( it = m.begin() ; it != m.end() ; it++ ){
int num = it->second ;
val = ( val * C[ num + n - i - 1 ][ n - i - 1 ] ) % mod ;
}
if( i & 1 )
ans = ( ans - val + mod ) % mod ;
else
ans = ( ans + val ) % mod ;
}
return ans ;
}
int main(){
// freopen("input.txt","r",stdin);
init() ;
while( cin >> n ){
m.clear();
for( int i = 1 ; i <= n ; i++ )
cin >> b[i] ;
cout << work() << endl;
}
return 0;
}