首页 > 代码库 > POJ 2992
POJ 2992
此题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;}
POJ 2992
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。