http://codeforces.com/contest/397/problem/C
给出n个数字,m = a[1] * a[2] * a[3] ... * a[n]
要求把m分成n个不一样的乘积,求方案数。
就是35分成2分的话,1 * 35 。35 * 1。5 * 7。7 * 5
首先数字很大,表示出来是不可能的。
考虑储存它的质因数,例如12。 12 = 2 * 2 * 3
如果要分成4分的话,首先对每一种质因数放。
例如2,有2个,可以表示为(4份)
2 * 2 * 1 * 1
2 * 1 * 2 * 1
......
4 * 1 * 1 * 1
..........
这是一个经典的组合数学问题,n个球,放在m个箱子,可以空,可以重叠。一共有C(n + m - 1, m - 1)种。
这里空的用了1来表示。
然后不对呀,这不是12的分解情况,它还有一个质因子嘛,3.
分成
3 * 1 * 1 * 1
1 * 3 * 1 * 1
1 * 1 * 3 * 1
1 * 1 * 1 * 3
,然后种数相乘,就是答案,为什么呢?比如(2 * 2 * 1 * 1) X (3 * 1 * 1 * 1) = (6 * 2 * 1 * 1),是一种情况。
因为有500个数字,如果每个数字都是2^30次方,一共有15000个2,但是格子最多500个。
可以预处理组合数C[15000][500]即可,不会爆内存,
一开始一直re,是我自己没分析好。、
最后也没预处理,因为没想到用C[15000][500]这样, 用的是逆元。我太水了太渣了
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #define MY "H:/CodeBlocks/project/CompareTwoFile/DataMy.txt", "w", stdout #define ANS "H:/CodeBlocks/project/CompareTwoFile/DataAns.txt", "w", stdout #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> map<int, int>mp; const int MOD = 1e9 + 7; LL quick_pow(LL a, LL b, LL MOD) { //求解 a^b%MOD的值 LL base = a % MOD; LL ans = 1; //相乘,所以这里是1 while (b) { if (b & 1) { ans = (ans * base) % MOD; //如果这里是很大的数据,就要用quick_mul } base = (base * base) % MOD; //notice。注意这里,每次的base是自己base倍 b >>= 1; } return ans; } LL C(LL n, LL m, LL MOD) { if (n < m) return 0; //防止sb地在循环,在lucas的时候 if (n == m) return 1; LL ans1 = 1; LL ans2 = 1; LL mx = max(n - m, m); //这个也是必要的。能约就约最大的那个 LL mi = n - mx; for (int i = 1; i <= mi; ++i) { ans1 = ans1 * (mx + i) %MOD; ans2 = ans2 * i % MOD; } return (ans1 * quick_pow(ans2, MOD - 2, MOD) % MOD); //这里放到最后进行,不然会很慢 } void work() { mp.clear(); int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) { int x; scanf("%d", &x); int end = (int)sqrt(x + 0.5); for (int j = 2; j <= end; ++j) { if (x % j == 0) { mp[j]++; x /= j; while (x % j == 0) { mp[j]++; x /= j; } end = (int)sqrt(x + 0.5); } } if (x != 1) mp[x]++; } LL ans = 1; for (map<int, int> :: iterator it = mp.begin(); it != mp.end(); ++it) { // cout << it->first << " " << it->second << endl; int val = it->second; // if (val > maxn) while(1); // ans *= C[val + n - 1][n - 1]; ans *= C(val + n - 1, n - 1, MOD); ans %= MOD; } printf("%I64d ", ans); } int main() { #ifdef local freopen("data.txt","r",stdin); #endif work(); return 0; }