此题A得艰难,应该是有很多组数据吧,使得容易超时。
直接求出组合数是不可能的,因而,只能把各个数都计算其各素因子个数,再计算即可。
而直接计算,必定是要超时的,所以,只好先预处理所有结果,再输出了。
首先筛选素数,分解0~440的素因子。
然后,Cnk=(n*(n-1)*(n-2)*...(n-k+1))/k!,计算,按各数所拆解素因子计算出组合数的素因子及其个数,再求出即可。
而对于Cn(k+1)=(n*(n-1)*(n-2)*...(n-k+1)*(n-k))/(k+1)!只需在Cnk的基础上递推过来,亦即再加上n-k的素因子个数减去k+1素因子个,否则,TLE
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; bool isprime[500]; int prime[500],np; int cnum[500][500]; __int64 Cnk[500][500]; void prim(){ int Max=500; memset(isprime,true,sizeof(isprime)); memset(cnum,0,sizeof(cnum)); np=0; int i,j; isprime[1]=false; for(i=2;i<Max;i++){ if(isprime[i]){ prime[np++]=i; for(j=i*i;j<Max;j+=i) isprime[j]=false; } } memset(cnum,0,sizeof(cnum)); for(int i=440;i>=0;i--){ int tmp=i; for(int j=0;prime[j]<=tmp;j++){ if(tmp%prime[j]==0){ while(tmp%prime[j]==0){ cnum[i][j]++; tmp/=prime[j]; } } } } } void divide(){ int ans[500]; for(int n=0;n<=440;n++){ for(int k=0;k<=n;k++){ Cnk[n][k]=1; if(k==0){ continue; } if(k==1){ for(int i=0;i<np;i++){ ans[i]=cnum[n][i]; } } else{ for(int i=0;i<np;i++){ ans[i]=ans[i]+cnum[n-k+1][i]-cnum[k][i]; } } for(int i=0;i<np;i++) Cnk[n][k]*=(__int64)(ans[i]+1); } } } int main(){ int n,k,tmp; prim(); divide(); while(scanf("%d%d",&n,&k)!=EOF){ printf("%I64d\n",Cnk[n][k]); } return 0; }
时间: 2024-10-19 14:46:31