这个题卡了我一个下午。
一直TLE,所以我推测测试数据一定是神多组。。
后来我发现每次读数据后都要重复算一遍连续数乘的因式分解,
所以把n!的分解方式全部预处理出来然后计算输出就行了。。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define N 432 typedef long long LL; const int cnt = 83; int p[400] = {2,3,5,7,11,13,17,19,23,29,//10 31,37,41,43,47,53,59,61,67,//9 71,73,79,83,89,97,101,103,107,//9 109,113,127,131,137,139,149,151,//8 157,163,167,173,179,181,191,193, 197,199,211,223,227,229,233,239, 241,251,257,263,269,271,277,281, 283,293,307,311,313,317,331,337, 347,349,353,359,367,373,379,383, 389,397,401,409,419,421,431}; int num[N+1][400]; void fac() { memset(num,0,sizeof(num)); for(int k=2;k<N;k++) for(int i=2;i<=k;i++) { int t = i; for(int j=0;j<cnt;j++) { while(t%p[j] == 0) { t /= p[j]; num[k][j]++; } if(t == 1)break; } } } int main() { fac(); LL ret[N+1][N+1]; for(int i=0;i<N;i++) for(int j=0;j<N;j++) ret[i][j] = -1; int n,k; while(~scanf("%d%d",&n,&k)) { if(ret[n][k]!=-1){printf("%I64d\n",ret[n][k]);continue;} ret[n][k] = 1LL; for(int i=0;i<cnt;i++) ret[n][k] *= (LL)(num[n][i]-num[n-k][i]-num[k][i]+1); printf("%I64d\n",ret[n][k]); } return 0; }