1. 程式人生 > >poj2992 divisors 求組合數的約數個數,階乘的質因數分解

poj2992 divisors 求組合數的約數個數,階乘的質因數分解

TP iostream 約數個數 PE printf for tinc 階乘 BE

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

  

poj2992 divisors 求組合數的約數個數,階乘的質因數分解