Codeforces 396A 数论,组合数学
Posted 树的种子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 396A 数论,组合数学相关的知识,希望对你有一定的参考价值。
题意:给一个a数组,求b 数组的方案数,但是要求两者乘积相同。
分析:
不可能将它们乘起来,对于每个数质因数分解,得到每个质因子个数,遍历这些质因子,将某个质因子放到 对应的盒子里面,可以不放,方案数就是一个组合数,用插板法。
这里的素数板子挺好的,一方面可以用来判断,一方面存起来。
组合数,可以考虑用乘法逆元。
每个质因子个数hash一下。
#include <bits/stdc++.h> using namespace std; const int MOD = 1e9 + 7; #define N 50009 typedef long long ll; const int maxnn = 15000+5; int C[maxnn][505]; void init() { memset(C, 0, sizeof(C)); C[0][0] = 1; C[1][0] = C[1][1] = 1; for(int i = 2; i < maxnn; ++i) { C[i][0] = C[i][i] = 1; for(int j = 1; j < i; ++j) { C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD; } } } bool vis[50009]; int primes[50009]; int num_prime; int get_primes (int m) { //获取一定范围内的素数 memset(vis,0,sizeof(vis)); for(int i=2;i<m;i++) { if(!vis[i]) primes[num_prime++]=i; for(int j=0;j<num_prime && i*primes[j]<m;j++) { vis[i*primes[j]]=1; if(!(i%primes[j])) break; } } return num_prime; } std::map<int, int> mp; void divide(int x) { int temp = (int)sqrt(x*1.0); for(int i=0;i<num_prime;i++) { if(primes[i]>temp) break; while(x%primes[i]==0) { mp[primes[i]]++; x /=primes[i]; } } if(x!=1) mp[x]++; } int main(int argc, char const *argv[]) { mp.clear(); init(); get_primes(N); int n,x; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&x); divide(x); } ll ans= 1; std::map<int, int> ::iterator p; for(p = mp.begin();p!=mp.end();p++) { int k = p->second; ans = ans * C[k+n-1][n-1] % MOD; } printf("%lld\n", ans); return 0; }
以上是关于Codeforces 396A 数论,组合数学的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 451 E. Devu and Flowers(组合数学,数论,容斥原理)
Codeforces 963A Alternating Sum 数论+数学
Codeforces 1106F Lunar New Year and a Recursive Sequence (数学线性代数线性递推数论BSGS扩展欧几里得算法)