poj2992 divisors 求组合数的约数个数,阶乘的质因数分解

Your task in this problem is to determine the number of divisors of Cnk. Just for fun -- or do you need any special reason for such a useful computation?

Input

The input consists of several instances. Each instance consists of a single line containing two integers n and k (0 ≤ k ≤ n ≤ 431), separated by a single space.

Output

For each instance, output a line containing exactly one integer -- the number of distinct divisors of Cnk. For the input instances, this number does not exceed 2 63 - 1.

Sample Input

5 1
6 3
10 4

Sample Output

2
6
16思路:计算约数个数的时候,可以类比数的唯一分解求约数个数;s=2^p1*3^p2*5^p3*-----num=(p1+1)*(p2+1)*(p3+1)*....如果求分数类型的约数个数...可以分解质因数之后在上面的个数-下面的个数即s__=2^(p1-p1_)*3^(p2-p2_)*----num=(p1-p1_+1)*(p2-p2_+1)*(p3-p3_+1)*---阶乘的质因数分解:  int cal(int n,int p) if(n<p)return 0;else return n/p+cal(n/p,p);
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int prime[500];bool vis[500];
typedef long long ll;int cnt;
void init(){
	for(int i=2;i<=431;i++){
		if(!vis[i]) for(int j=i*2;j<=431;j+=i) vis[j]=1;
	}
	for(int i=2;i<=431;i++){
		if(!vis[i]) prime[++cnt]=i;
	}
}
int num1[500],num2[500];
int cal(int n,int p){
	if(n<p) return 0;
	else return n/p+cal(n/p,p);
}
int main(){
	init();int n,m;
	//std::ios::sync_with_stdio(false);cin.tie(0);
	//for(int i=1;i<=83;i++) cout<<prime[i]<<endl;
	while(~scanf("%d%d",&n,&m)){
		ll ans=1;
		memset(num1,0,sizeof(num1));
		memset(num2,0,sizeof(num2));
		for(int i=1;prime[i]<=n&&i<=cnt;i++){
			num1[i]=cal(n,prime[i]);
			num2[i]=cal(m,prime[i])+cal(n-m,prime[i]);
			ans*=(num1[i]-num2[i]+1);
			//cout<<ans<<endl;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/vainglory/p/9075013.html

时间: 2024-08-26 11:14:27

poj2992 divisors 求组合数的约数个数,阶乘的质因数分解的相关文章

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 求组合数的因子个数

求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

【线性筛】【筛法求素数】【约数个数定理】URAL - 2070 - Interesting Numbers

素数必然符合题意. 对于合数,如若它是某个素数x的k次方(k为某个素数y减去1),一定不符合题意.只需找出这些数. 由约数个数定理,其他合数一定符合题意. 就从小到大枚举素数,然后把它的素数-1次方都排除即可. #include<cstdio> #include<cmath> using namespace std; #define MAXP 1000100 #define EPS 0.00000001 typedef long long ll; ll L,R; bool isNo

[2011山东ACM省赛] Binomial Coeffcients(求组合数)

Binomial Coeffcients nid=24#time" style="padding-bottom:0px; margin:0px; padding-left:0px; padding-right:0px; color:rgb(83,113,197); text-decoration:none; padding-top:0px"> Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描写叙述 输入

UVA294DIvisors(唯一分解定理+约数个数)

题目链接 题意:输入两个整数L,U(L <= U <= 1000000000, u - l <= 10000),统计区间[L,U]的整数中哪一个的正约数最多,多个输出最小的那个 本来想着用欧拉函数,打个表求所有的约数个数,但是u太大,直接暴力求解 利用唯一分解定理,刷选出根号1000000000的素数,对l,u区间的每一个数进行分解 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm

hdu 6069 Counting Divisors(求因子的个数)

Counting Divisors Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 3170    Accepted Submission(s): 1184 Problem Description In mathematics, the function d(n) denotes the number of divisors of

数论线性筛总结 (素数筛,欧拉函数筛,莫比乌斯函数筛,前n个数的约数个数筛)

线性筛 线性筛在数论中起着至关重要的作用,可以大大降低求解一些问题的时间复杂度,使用线性筛有个前提(除了素数筛)所求函数必须是数论上定义的积性函数,即对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数,若a,b不互质也满足的话则称作完全积性函数,下面说明每个筛子是怎么筛的. 最基础的是素数筛,其它三个筛都是以素数筛为前提 素数筛 void get_prime() { int pnum = 0; for(int i = 2;

求组合数小结

今天学了一天数学,觉得自己都要转竞了23333 题目链接https://vjudge.net/contest/282927#problem/E 这里说一说求组合数的方法吧 其实就是求阶乘及其逆元的方法: 规定mod为模数,n为数据规模 1.mod为素数 费马小定理:nlogn 线性求逆元(n较小) 2.mod不为素数 欧拉筛出两个阶乘的素数,再计算出每个素数的次幂,最后快速幂乘起来即可 详见 n = read(),p = read(); ans = 1; for(int i = 2;i <= 2

求组合数C(m,n)的多种计算方法

https://ac.nowcoder.com/discuss/187813?type=101&order=0&pos=1&page=0 https://blog.csdn.net/shadandeajian/article/details/82084087 1.简单法---适合n,m很小 #include<bits/stdc++.h> using namespace std; const int MAXN = 1000; int C[MAXN+1][MAXN+1];