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 ...
随机推荐
- WPF动画 storyboard
<Window x:Class="StoryBoard.MainWindow" xmlns="http://schemas.microsoft.com/winfx/ ...
- 线程操作API
线程操作API 1.currentThread 2.getId() .getName().getPriority().getStart.isAlive().isDaemon().isInterrupt ...
- 11G ORACLE RAC DBCA 无法识别asm磁盘组
ASM磁盘无法识别几种现象: 1) gi家目录或者其子目录权限错误 2)asm磁盘的权限错误 3)asm实例未启动或者asm磁盘组没有mount上 4)asm磁盘组资源没有在线 5)oracle用户的 ...
- RCF
1. RCF: 纯c++的RPC, 不引入IDL, 大量用到boost,比较强大.2. casocklib: protobuf + asio 较完善实现3. eventrpc: protobuf + ...
- cocos2dx中的CCLayerColor
颜色图层在游戏中主要用来烘托背景,可以按照RGB设置填充颜色,同时还可以设置图层的透明度(opacity),常用于显示背景 颜色图层还存在一个特殊的子类:CCLayerGradient,是具有颜色渐变 ...
- 使用itunes同步ios时丢失照片恢复
因没有备份,在使用同步功能后,发现照片被清空了,找到恢复方法,分享之! from:http://modmyi.com/forums/native-iphone-ipod-touch-app-discu ...
- ORACLE 检查数据库表中是否存在不规范字 段的语句参考.sql
--查看是否有除number,char,date,varchar2,clob/blob之外的类型,比如:NVARCHAR2,TIMESTAMP(6),FLOATSELECT DISTINCT a.DA ...
- 向Array中添加插入排序
插入排序思路 从第二个元素开始和它前面的元素进行比较,如果比前面的元素小,那么前面的元素向后移动,否则就将此元素插入到相应的位置. 插入排序实现 Function.prototype.method = ...
- volley框架 出现at com.android.volley.Request.<init>
请求json数据的时候出现这种情况: 原因: // 访问网络,初始化详情 JsonObjectRequest jr = new JsonObjectRequest(Request.Method.GET ...
- EntityFramework走马观花之CRUD(上)
对于任何一个ORM框架,CRUD都是其核心功能,可以这么说,CRUD功能实现得好坏,直接决定了此ORM框架的命运. CRUD是英文Create.Read.Update.Delete四个单词的缩写,对应 ...