POJ 2992 Divisors (求因子个数)
题意:给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 (求因子个数)的更多相关文章
- Trailing Zeroes (I) LightOJ - 1028(求因子个数)
题意: 给出一个N 求N有多少个别的进制的数有后导零 解析: 对于一个别的进制的数要转化为10进制 (我们暂且只分析二进制就好啦) An * 2^(n-1) + An-1 * 2^(n-2) + `` ...
- Almost All Divisors(求因子个数及思维)
---恢复内容开始--- We guessed some integer number xx. You are given a list of almost all its divisors. Alm ...
- LightOj1028 - Trailing Zeroes (I)---求因子个数
题目链接:http://lightoj.com/volume_showproblem.php?problem=1028 题意:给你一个数 n (1<=n<=10^12), 然后我们可以把它 ...
- Easy Number Challenge(暴力,求因子个数)
Easy Number Challenge Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I ...
- poj 2992 Divisors (素数打表+阶乘因子求解)
Divisors Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9617 Accepted: 2821 Descript ...
- poj 2992 Divisors 整数分解
设m=C(n,k)=n!/((n-k)!*k!) 问题:求m的因数的个数 将m分解质因数得到 p1有a1个 p2有a2个 .... 因为每一个质因数能够取0~ai个(所有取0就是1,所有取ai就是m) ...
- POJ 2992 Divisors
每个数都可以分解成素数的乘积: 写成指数形式:n=p1^e1*p2^e2*...*pn^en:(p都是素数) 那么n的因数的数量m=(e1+1)*(e2+1)*...*(en+1): 所以用筛选法筛出 ...
- 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, ...
- Divisors (求解组合数因子个数)【唯一分解定理】
Divisors 题目链接(点击) Your task in this problem is to determine the number of divisors of Cnk. Just for ...
随机推荐
- C/C++ 对常见字符串库函数的实现
在c中的string.h头文件中存在很多对字符串进行操作的函数,利用这些函数可以方便的对字符串进行操作.下面将对常见的字符串函数进行解释和实现. strcpy 函数原型:char* _strcpy(c ...
- JQuery ----文档处理
1.append(content|fn) 概述 向每个匹配的元素内部追加内容. 这个操作与对指定的元素执行appendChild方法,将它们添加到文档中的情况类似. 2.appendTo(conten ...
- “后PC”时代来临
“后PC”时代来临 数年前,喜达屋酒店及度假村国际集团将总部搬迁至美国康涅狄格州斯坦福,这也让公司首席执行官Frits van Paasschen有机会“除尘换新”. 那么,Frits van Paa ...
- MongoDB学习笔记-数据库命令
概念 数据库命令(database command)是一种非常特殊类型的查询.文档的创建.更新.删除及查询都属于数据库命令的范畴,它还包含管理性的任务(比如关闭服务器和克隆数据库).统计数据及执行聚合 ...
- 如何安装altium designer 10
http://jingyan.baidu.com/article/4dc4084881e2bdc8d946f1f3.html
- Linux内核内存管理
<Linux内核设计与实现>读书笔记(十二)- 内存管理 内核的内存使用不像用户空间那样随意,内核的内存出现错误时也只有靠自己来解决(用户空间的内存错误可以抛给内核来解决). 所有内核 ...
- 在VS2010中ActiveX控件注册方法,使用regsvr32命令
上一篇小编展示了如何设置VS2010自带的ActiveX控件的容器测试程序,现在为大家演示一下如何注册ActiveX控件. 首先简单了解一下ActiveX控件的知识,ActiveX控件:简单来说,就是 ...
- svn中的图标解释
黄色感叹号(有冲突): --这是有冲突了,冲突就是说你对某个文件进行了修改,别人也对这个文件进行了修改,别人抢在你提交之前先提交了,这时你再提交就会被提示发生冲突,而不 允许你提交,防止你的提交覆盖了 ...
- 面向对象设计SOLID五大原则
转载自:码农社区,http://w3croom.com/read.php?tid-4522.html 今天我给大家带来的是面向对象设计SOLID五大原则的经典解说. 我们知道,面向对象对于 ...
- Log4Net学习【二】
Log4Net结构详解 当我们在描述为系统做日志这个动作的时候,实际上描述了3个点:做日志,其实就是在规定,在什么地方 用什么日志记录器 以什么样的格式做日志.把三个最重要的点抽取出来,即什么地方,日 ...