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;
}

  

时间: 2024-10-19 14:46:31

POJ 2992的相关文章

poj 2992 Divisors 整数分解

设m=C(n,k)=n!/((n-k)!*k!) 问题:求m的因数的个数 将m分解质因数得到 p1有a1个 p2有a2个 .... 由于每个质因数可以取0~ai个(全部取0就是1,全部取ai就是m)最后的答案就是(a1+1)*(a2+1)*....* 注意不能直接将m分解,因为太大,所以要先分解n,n-k,k,根据他们再来加减. #include <iostream> #include <cstdio> #include <cmath> #include<cstr

POJ 2992 Divisors 求组合数因子个数

题目来源:POJ 2992 Divisors 题意:... 思路:素数分解的唯一性 一个数可以被分解成若干素数相乘 p1^x1*p2^x2*...*pn^xn 根据乘法原理 因子数为 (x1+1)*(x2+1)*...*(xn+1) 不能直接求出组合数 会溢出 也不能把每个乘的数分解因子 这样会超时 C(N,M)=N!/(M!*(N-M)!) 另dp[i][j] 代表为i的阶乘中j因子的个数(j是素数) 那么i素数的个数为dp[n][i]-dp[m][i]-dp[n-m][i] 最后for循环从

poj 2992 Divisors

题目链接:http://poj.org/problem?id=2992 题目大意:就是叫你求组合数C(n,m)的因子的个数. 思路:求解这题需要用到以下几个定理 1.对任意的n,可以这么表示 n=p1^e1*p2^e2*p3*e3*......pn^en .(p1,p2,p3......pn都为素数) 2.对任意的n的因子数为:(1+e1)*(1+e2)*(1+e3)*......*(1+en) 3.n!的素数因子=(n-1)!的素数因子+n的素数因子 4.C(n,k)的素因子=n!的素因子 -

POJ 2992 求组合数的因子个数

求C(n,k)的因子个数 C(n,k) = (n*(n-1)*...*(n-k+1))/(1*2*...*k) = p1^k1 * p2^k2 * ... * pt^kt 这里只要计算出分子中素数因子个数减去分母中的个数 然后每一种因子都有 (cnt+1)种取的可能,乘一下就出来了 但是不能逐个因子分解,试了两次都错了,后来初始的时候,先将这432个数提前预处理分解好保存到vector中 然后用的时候直接提取就行 不然会因为数据量太大超时的 1 #include <iostream> 2 #i

组合数学+整数分解 POJ 2992 Divisors

题意:给n,k,求C(n,k)的约数的个数. 由于C(n,k)=n!/(k!*(n-k)!),所以只要分别把分子分母的素因子的次数求出来,再用分子的每个素因子的次数减去分母的每个素因子的次数就可以得到C(n,k)的素数分解式,约数个数就等于(p1+1)(p2+1)*...*(pn+1).这道题n,k的范围都是四百多,按理说O(N^2)的算法可以过的,但是测试数据太多了,暴力的方法会TLE.看别人的报告知道了求N!的某个素因子次数的递归算法,然后枚举每个素数,求出它在阶乘中的次数,就可以AC了.

POJ 2992-Divisors(求组合数质因子的个数)

Divisors Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2992 Appoint description:  System Crawler  (2015-04-24) Description Your task in this problem is to determine the number of divisors of C

组合数取模(转载)

本文转自:http://blog.csdn.net/skywalkert/article/details/52553048 0. 写在前面 在程序设计中,可能会碰到多种类型的计数问题,其中不少涉及到组合数的计算,所以笔者写下这么一篇文章,期望能解决一些常规的组合数求模问题.以下部分内容改编自AekdyCoin的<组合数求模>,而且为了感谢他对(懵懂的)笔者的启发,这篇文章的标题与其文章相同.另外,感谢Picks将多项式运算的技巧在中国进行推广,感谢51nod提供了许多有趣的数论题目,感谢fot

从“n!末尾有多少个0”谈起

在学习循环控制结构的时候,我们经常会看到这样一道例题或习题.问n!末尾有多少个0?POJ 1401就是这样的一道题. [例1]Factorial (POJ 1401). Description The most important part of a GSM network is so called Base Transceiver Station (BTS). These transceivers form the areas called cells (this term gave the

poj:2992 因子数量

题意: 求 组合数c(n,k)的因子数量 由算术基本定理很容易求得,不过第一次却T了,加了好多预处理,o1查询,才过 #include <iostream> #include <stdio.h> #include<string.h> #include<algorithm> #include<string> #include<ctype.h> using namespace std; #define I64d lld int prime