【(阶乘的质因数分解)算组合数】【TOJ4111】【Binomial efficient】
n<=10^6
m<=10^6
p=2^32
用unsigned int 可以避免取模
我写的SB超时 阶乘分解代码
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 using namespace std; const unsigned int N=1000000+5; unsigned int tag[N],p[N],z[N],mm[N]; unsigned int cnt = 0; unsigned int n,m; unsigned int quickpow(unsigned int m,unsigned int n) { unsigned int b = 1; while (n > 0) { if (n & 1) b = (b*m); n = n >> 1 ; m = (m*m); } return b; } void get_prime() { tag[1]=1; tag[0]=1; for (unsigned int i = 2; i < N; i++) { if (!tag[i]) p[cnt++] = i; for (unsigned int j = 0; j < cnt && p[j] * i < N; j++) { tag[i*p[j]] = 1; if (i % p[j] == 0) break; } } } unsigned int FIND(unsigned int x) { unsigned int l=0,r=cnt-1; while(l<=r) { unsigned int m=(l+r)/2; if(p[m]==x) return m; else if(p[m]<x) l=m+1; else r=m-1; } } void fenjie(unsigned int *a,unsigned int d) { for(unsigned int i=0;i<cnt&&p[i]<=sqrt(d);i++) { while(d%p[i]==0) { d=d/p[i]; a[i]++; } } if(tag[d]==0) { unsigned int t=FIND(d); a[t]++; } } int main() { // freopen("a.in","r",stdin); get_prime(); int T; cin>>T; while(T--) { cin>>n>>m; memset(z,0,sizeof(z)); memset(mm,0,sizeof(mm)); for(unsigned int i=n;i>=n-m+1;i--) fenjie(z,i); for(unsigned int i=1;i<=m;i++) fenjie(mm,i); unsigned int ans=1; for(unsigned int i=0;i<cnt;i++) { z[i]=z[i]-mm[i]; ans=ans*quickpow(p[i],z[i]); } printf("%u\n",ans); } }
利用阶乘的质因数分解!
比如250!
1*2*3*4*5*6*7*8*9*10*11*12*13*14.....250
中3的质因子个数 除了3后变成(不是倍数的不管)计算3^1次方的为250/3个
又变成 1 2 3 .....250除3
重复上面 知道 3^2 为250/(3^2)
所以阶乘的质因数分解是另外的简单算法
void getcn(int n) { int ans = 0; int i; for (i = 1; i <= prime[0] && prime[i] <= n; i++) { int tmp = n; while (tmp) { num[i] += tmp / prime[i]; tmp /= prime[i]; } } num[0] = i; }
所以最后的代码是
#include <string.h> #include <iostream> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string> #include <algorithm> #include <vector> #include <string.h> #include <time.h> #include <queue> #include <stack> #include <map> #include <set> #include <sstream> #define INF 0x3f3f3f3f #define MAXN 1000005 #define Precision 100005 #define MAX_INT 2147483647 #define Pi acos(-1.0) #define lowbit(x) ((x)&(-x)) #define Lson root<<1,left,mid #define Rson root<<1|1,mid+1,right #define LL long long #define ULL unsigned long long #define fresh(x) memset(x,0,sizeof(x)) using namespace std; int prime[MAXN]; int num[MAXN]; void print() { <span style="white-space:pre"> </span>memset(prime, 0, sizeof(prime)); <span style="white-space:pre"> </span>for (int i = 2; i <= 1000000; i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if (!prime[i]) prime[++prime[0]] = i; <span style="white-space:pre"> </span>for (int j = 1; j <= prime[0] && prime[j] <= 1000000 / i; j++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>prime[prime[j]*i] = 1; <span style="white-space:pre"> </span>if (i % prime[j] == 0) break; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} } unsigned qpow(unsigned a, unsigned b) { <span style="white-space:pre"> </span>unsigned ans = 1; <span style="white-space:pre"> </span>while (b) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if (b & 1) <span style="white-space:pre"> </span>ans *= a; <span style="white-space:pre"> </span>b >>= 1; <span style="white-space:pre"> </span>a *= a; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return ans; } void getcn(int n) { <span style="white-space:pre"> </span>int ans = 0; <span style="white-space:pre"> </span>int i; <span style="white-space:pre"> </span>for (i = 1; i <= prime[0] && prime[i] <= n; i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>int tmp = n; <span style="white-space:pre"> </span>while (tmp) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>num[i] += tmp / prime[i]; <span style="white-space:pre"> </span>tmp /= prime[i]; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>num[0] = i; } void getcm(int m) { <span style="white-space:pre"> </span>int ans = 0; <span style="white-space:pre"> </span>int i; <span style="white-space:pre"> </span>for (i = 1; i <= prime[0] && prime[i] <= m; i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>int tmp = m; <span style="white-space:pre"> </span>while (tmp) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>num[i] -= tmp / prime[i]; <span style="white-space:pre"> </span>tmp /= prime[i]; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} } int main() { <span style="white-space:pre"> </span>int n, m, T; <span style="white-space:pre"> </span>print(); <span style="white-space:pre"> </span>//printf("%d\n", prime[prime[0]]); <span style="white-space:pre"> </span>//cout << prime[0]; <span style="white-space:pre"> </span>scanf("%d", &T); <span style="white-space:pre"> </span>while (T--) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>memset(num, 0, sizeof(num)); <span style="white-space:pre"> </span>scanf("%d%d", &n, &m); <span style="white-space:pre"> </span>getcn(n); <span style="white-space:pre"> </span>getcm(m); <span style="white-space:pre"> </span>getcm(n - m); <span style="white-space:pre"> </span>unsigned ans = 1; <span style="white-space:pre"> </span>for (int i = 1; i <= num[0]; i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>ans *= qpow(prime[i], num[i]); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>printf("%u\n", ans); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return 0; }