G29 隔板法
视频链接:https://www.bilibili.com/video/BV1ge4y177mb/
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 150, P = 1000; int C[1000][100][N]; int qpow(int a, int b){//快速幂 int res = 1; while(b){ if(b & 1) res = res*a%P; a = a*a%P; b >>= 1; } return res; } void add(int c[],int a[],int b[]){//高精度 for(int i = 0; i < N; i++){ c[i] += a[i]+b[i]; c[i+1] += c[i]/10; c[i] %= 10; } } void getC(int n, int k){//组合数 for(int i=0; i<n; i++) for(int j=0; j<=i && j<k; j++) if(j == 0) C[i][j][0] = 1; else add(C[i][j],C[i-1][j],C[i-1][j-1]); } int main(){ int k, x; cin >> k >> x; int n = qpow(x%P, x); getC(n, k); int i = N-1; while(C[n-1][k-1][i]==0) i--; while(i>=0) printf("%d", C[n-1][k-1][i--]); return 0; }
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 1010; int P=1000; int prim[N], vis[N], cnt; int qpow(int a, int b){ //快速幂 int res = 1; while(b){ if(b & 1) res = res*a%P; a = a*a%P; b >>= 1; } return res; } void get_prim(int n){ //筛素数 for(int i = 2; i <= n; i ++){ if(!vis[i]) prim[cnt++] = i; for(int j=0; i*prim[j]<=n; j++){ vis[i*prim[j]] = 1; if(i%prim[j] == 0) break; } } } int get(int n,int p){ //n!中p的个数 int s = 0; while(n) s += n/p, n /= p; return s; } int getps(int n,int m,int p){//C中p的个数 return get(n,p)-get(m,p)-get(n-m,p); } void mul(int C[],int p,int &len){//高精度 int t = 0; for(int i=0; i<len; i++){ t += C[i]*p; C[i] = t%10; t /= 10; } while(t){ C[len++] = t%10; t /= 10; } } int main(){ int k, x; cin >> k >> x; int n = qpow(x%P,x); n--, k--; get_prim(n); int C[N], len=1; C[0]=1; for(int i=0; i<cnt; i++){ int p = prim[i]; int s = getps(n,k,p); while(s--) mul(C,p,len); } for(int i=len-1; i>=0; i--) printf("%d", C[i]); return 0; }
#include<iostream> #include<cstdio> using namespace std; int P=1000; int C[10100],len=1; int qpow(int a, int b){ int res = 1; while(b){ if(b & 1) res = res*a%P; a = a*a%P; b >>= 1; } return res; } void getC(int n,int m){ C[1]=1; // 求 n*...*(n-m+1) for(int i=m+1;i<=n;i++){ for(int j=1;j<=len;j++) C[j]*=i; int t=0; for(int j=1;j<=len;j++){ t+=C[j]; C[j]=t%10; t/=10; } while(t){ C[++len]=t%10; t/=10; } } // 除以 2*...*(n-m) for(int i=2;i<=n-m;i++){ int t=0; for(int j=len;j>=1;j--){ t*=10; t+=C[j]; C[j]=0; if(t>i){ C[j]=t/i; t%=i; } } while(C[len]==0) len--; } } int main(){ int k,x; cin>>k>>x; int n=qpow(x%P,x); getC(n-1,k-1); for(int i=len;i>=1;i--) printf("%d", C[i]); return 0; }