题目:a1*a2*...*an=b1*b2*…*bn,(ai > 1) 给出b序列,求a序列有多少种。
先不考虑ai > 1这个条件。可以通过费解b_i的质因子得到如下公式:
∏b_i = ∏(p_i^k_i);
pi是∏bi 的某个质因子。
因为a_i 共有n个,所以把每个p_i填到这n个空位置里边去。对于p_i,有C(k_i + n - 1, n - 1);
证明见:http://hi.baidu.com/pp_5/blog/item/73798043ec77781f72f05d51.html/cmtid/6aff22f08c5c85a1a50f523d
显然,所有的p[]的值为 ∏C(k_i + n - 1, n - 1); (上午问ftiasch❤trl大牛时就是这个地方没想明白。。。让他体会了一把对牛弹琴的感觉。。。深表歉意。)
然后考虑ai > 1这个条件。
已知容次原理:
设Ai表示i位置为1这种状态。 则 answer =
根据容斥原理枚举Ai, Aj, Ak...位置为1的状态。。。。
View Code
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #include <map> #include <sstream> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) x < y ? x : y #define Max(x, y) x < y ? y : x #define E(x) (1 << (x)) const double eps = 1e-4; typedef long long LL; const int inf = ~0u>>2; using namespace std; const int N = 110; const int M = 1000010; const int MOD = 1e9 + 7; int c[N][N]; int k[M], t[M]; int num, n; int prime[N*20]; bool vis[N*20]; int cnt; void get_prime() { CL(vis, true); int i, j; for(i = 2; i < N*20; ++i) { for(j = i*i; j < N*20; j += i) { vis[j] = false; } } cnt = 0; for(i = 2; i < N*20; ++i) { if(vis[i]) prime[cnt++] = i; } } void init() { get_prime(); CL(c, 0); int i , j; for(i = 0; i < N; ++i) c[i][0] = c[i][i] = 1; for(i = 2; i < N; ++i) { for(j = 1; j < i; ++j) { c[i][j] = (c[i-1][j] + c[i-1][j-1])%MOD; } } } LL solve(int x) { int m = n, flag = 1, i; for(i = 0; i < n; ++i) { if(((1<<i)&x) == 0) { flag *= -1; m--; } } LL tmp = 1; for(i = 0; i < num; ++i) { tmp = tmp*LL(c[k[i]+m-1][m-1])%MOD; } //printf("%d\n", tmp*flag); return tmp*flag; } int main() { //freopen("data.in", "r", stdin); init(); int x, i, j; LL ans; while(~scanf("%d", &n)) { CL(t, 0); for(i = 0; i < n; ++i) { scanf("%d", &x); for(j = 0; prime[j]*prime[j] <= x; ++j) { if(x%prime[j] == 0) { while(x%prime[j] == 0) { t[prime[j]]++; x /= prime[j]; } } } if(x != 1) t[x]++; } num = 0; for(i = 2; i < M; ++i) { if(t[i] != 0) { k[num++] = t[i]; } } ans = 0; //从N状态开始枚举。。。二进制位为1表示那一位的a_i不等于1,为0则表示等于1。因为proh(a_i) = proh(b_i)所以,a_i不可能全为0。。。 for(i = (1<<n)-1; i >= 1; --i) { ans = (ans + solve(i))%MOD; } cout << (ans%MOD + MOD)%MOD << endl; } return 0; }