题意:给n和k,求组合C(n,k)的因子个数。

这道题,若一开始先预处理出C[i][j]的大小,再按普通方法枚举2~sqrt(C[i][j])来求解对应的因子个数,会TLE。
所以得用别的方法。

在说方法前,先说一个n!的性质:
n!的素因子分解中的素数p的个数为
n/p+n/(p^2)+...+n/(p^k)+...

《ACM-ICPC程序设计系列 数论及应用》上的方法,200+ms:
首先先求解435以内的素因子。
然后预处理出j!中每个素因子的个数,公式如下:
num[j][i]=j/prime[i]+num[j/prime[i]][i];

设n!中素因子p的个数为:a=n/p+n/(p^2)+...+n/(p^k)+...
那么(n/p)!中素因子p的个数为:b=n/(p^2)+...+n/(p^k)+...
很显然a=b+n/p,因此可以利用上述递推公式预处理出所有的j!中每个素因子的个数。

接下来就可以预处理出C(i,j)的因子个数,然后一切就好办了。

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h> using namespace std;
const int maxn=;
bool isprime[maxn];
int prime[maxn];
int cnt=;
int num[maxn][maxn]; //num[i][j]表示i!中素因子prime[j]的个数。
long long C[maxn][maxn]; //C[i][j](0<=j<=i)表示组合C(i,j)的因子个数。
void init(){
memset(isprime,true,sizeof(isprime));
for(int i=;i<maxn;i++){
if(isprime[i]){
prime[cnt++]=i;
for(int j=i*;j<maxn;j+=i)
isprime[j]=false;
}
}
memset(num,,sizeof(num));
for(int i=;i<cnt;i++){
for(int j=;j<maxn;j++)
num[j][i]=j/prime[i]+num[j/prime[i]][i];
}
//预处理出C(i,j)的因子个数
for(int i=;i<maxn;i++){
for(int j=;j<i;j++){
C[i][j]=;
for(int k=;k<cnt;k++){
int d=num[i][k]-num[i-j][k]-num[j][k];
if(d)
C[i][j]*=d+;
}
}
}
}
int main()
{
init();
int n,k;
while(scanf("%d%d",&n,&k)!=EOF){
if(n==k ||k==)
printf("1\n");
else
printf("%I64d\n",C[n][k]);
}
return ;
}

我的方法没有预处理,每次读取n和k后,利用公式计算n!,k!,(n-k)!的各个因素的个数,最后再总的求。时间600多ms。

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h> using namespace std;
const int maxn=;
bool isprime[maxn];
int prime[maxn];
int cnt=;
int num[maxn];
void init(){
memset(isprime,true,sizeof(isprime));
for(int i=;i<maxn;i++){
if(isprime[i]){
prime[cnt++]=i;
for(int j=i*;j<maxn;j+=i)
isprime[j]=false;
}
}
}
//求n!的各个素因子的个数
void countnum1(int n){
for(int i=;i<cnt && prime[i]<=n;i++){
int c=,p=prime[i];
while(n/p){
c+=n/p;
p*=prime[i];
}
num[prime[i]]+=c; //在分子上,是+=c。 }
}
void countnum2(int n){
for(int i=;i<cnt && prime[i]<=n;i++){
int c=,p=prime[i];
while(n/p){
c+=n/p;
p*=prime[i];
}
num[prime[i]]-=c; //分母,是-=c
}
}
int main()
{
init();
int n,k;
while(scanf("%d%d",&n,&k)!=EOF){
memset(num,,sizeof(num));
countnum1(n);
countnum2(n-k);
countnum2(k);
long long ret=;
for(int i=;i<cnt;i++){
if(num[prime[i]]){
ret*=(num[prime[i]]+);
}
}
printf("%I64d\n",ret);
}
return ;
}

POJ 2992 Divisors (求因子个数)的更多相关文章

  1. Trailing Zeroes (I) LightOJ - 1028(求因子个数)

    题意: 给出一个N 求N有多少个别的进制的数有后导零 解析: 对于一个别的进制的数要转化为10进制 (我们暂且只分析二进制就好啦) An * 2^(n-1) + An-1 * 2^(n-2) + `` ...

  2. Almost All Divisors(求因子个数及思维)

    ---恢复内容开始--- We guessed some integer number xx. You are given a list of almost all its divisors. Alm ...

  3. LightOj1028 - Trailing Zeroes (I)---求因子个数

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1028 题意:给你一个数 n (1<=n<=10^12), 然后我们可以把它 ...

  4. Easy Number Challenge(暴力,求因子个数)

    Easy Number Challenge Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I ...

  5. poj 2992 Divisors (素数打表+阶乘因子求解)

    Divisors Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9617   Accepted: 2821 Descript ...

  6. poj 2992 Divisors 整数分解

    设m=C(n,k)=n!/((n-k)!*k!) 问题:求m的因数的个数 将m分解质因数得到 p1有a1个 p2有a2个 .... 因为每一个质因数能够取0~ai个(所有取0就是1,所有取ai就是m) ...

  7. POJ 2992 Divisors

    每个数都可以分解成素数的乘积: 写成指数形式:n=p1^e1*p2^e2*...*pn^en:(p都是素数) 那么n的因数的数量m=(e1+1)*(e2+1)*...*(en+1): 所以用筛选法筛出 ...

  8. HDU-1492-The number of divisors(约数) about Humble Numbers -求因子总数+唯一分解定理的变形

    A number whose only prime factors are 2,3,5 or 7 is called a humble number. The sequence 1, 2, 3, 4, ...

  9. Divisors (求解组合数因子个数)【唯一分解定理】

    Divisors 题目链接(点击) Your task in this problem is to determine the number of divisors of Cnk. Just for ...

随机推荐

  1. C/C++ 对常见字符串库函数的实现

    在c中的string.h头文件中存在很多对字符串进行操作的函数,利用这些函数可以方便的对字符串进行操作.下面将对常见的字符串函数进行解释和实现. strcpy 函数原型:char* _strcpy(c ...

  2. JQuery ----文档处理

    1.append(content|fn) 概述 向每个匹配的元素内部追加内容. 这个操作与对指定的元素执行appendChild方法,将它们添加到文档中的情况类似. 2.appendTo(conten ...

  3. “后PC”时代来临

    “后PC”时代来临 数年前,喜达屋酒店及度假村国际集团将总部搬迁至美国康涅狄格州斯坦福,这也让公司首席执行官Frits van Paasschen有机会“除尘换新”. 那么,Frits van Paa ...

  4. MongoDB学习笔记-数据库命令

    概念 数据库命令(database command)是一种非常特殊类型的查询.文档的创建.更新.删除及查询都属于数据库命令的范畴,它还包含管理性的任务(比如关闭服务器和克隆数据库).统计数据及执行聚合 ...

  5. 如何安装altium designer 10

    http://jingyan.baidu.com/article/4dc4084881e2bdc8d946f1f3.html

  6. Linux内核内存管理

    <Linux内核设计与实现>读书笔记(十二)- 内存管理   内核的内存使用不像用户空间那样随意,内核的内存出现错误时也只有靠自己来解决(用户空间的内存错误可以抛给内核来解决). 所有内核 ...

  7. 在VS2010中ActiveX控件注册方法,使用regsvr32命令

    上一篇小编展示了如何设置VS2010自带的ActiveX控件的容器测试程序,现在为大家演示一下如何注册ActiveX控件. 首先简单了解一下ActiveX控件的知识,ActiveX控件:简单来说,就是 ...

  8. svn中的图标解释

    黄色感叹号(有冲突): --这是有冲突了,冲突就是说你对某个文件进行了修改,别人也对这个文件进行了修改,别人抢在你提交之前先提交了,这时你再提交就会被提示发生冲突,而不 允许你提交,防止你的提交覆盖了 ...

  9. 面向对象设计SOLID五大原则

    转载自:码农社区,http://w3croom.com/read.php?tid-4522.html 今天我给大家带来的是面向对象设计SOLID五大原则的经典解说.       我们知道,面向对象对于 ...

  10. Log4Net学习【二】

    Log4Net结构详解 当我们在描述为系统做日志这个动作的时候,实际上描述了3个点:做日志,其实就是在规定,在什么地方 用什么日志记录器 以什么样的格式做日志.把三个最重要的点抽取出来,即什么地方,日 ...