1. 程式人生 > >HDU 4390 Number Sequence (容斥原理+組合計數)

HDU 4390 Number Sequence (容斥原理+組合計數)

osi freopen ret dsm algo .cn iterator push_back man

HDU 4390

題意:

大概就是這樣。不翻譯了:
Given a number sequence b1,b2bn.
Please count how many number sequences a1,a2,...,ansatisfy the condition thata1?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?C1nxi=1Cn?2mi+n?2+C2nxi=1Cn?3mi+n?3?...Cn?1nxi=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; }

HDU 4390 Number Sequence (容斥原理+組合計數)