Divisors POJ - 2992
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
题意:
求组合数 的因子个数
分析:
根据公式:
同样是运用算术基本定理
我们枚举每一个素因子p,求出n!中多个p记为cnt1,k!中多少个p记为cnt2,(n-k)!中有多少个p记为cnt3
因为k!和(n-k)!作为分母因此势必会减少n!中的p,那么整个组合数中素因子p的个数应该是
cnt1-cnt2-cnt3
根据约数个数求和公式可以直接求出
code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 500;
bool isprime[maxn];
int prime[maxn],cnt;
void init(){
cnt = 0;
memset(isprime,true,sizeof(isprime));
isprime[0] = isprime[1] = false;
for(int i = 2; i < 500; i++){
if(isprime[i]){
prime[cnt++] = i;
for(int j = i + i; j < 500; j += i){
isprime[j] = false;
}
}
}
}
int resolve(int n,int p){
int ans = 0;
while(n){
ans += n / p;
n /= p;
}
return ans;
}//计算阶乘中含有多少个p
int main(){
init();
int n,k;
while(~scanf("%d%d",&n,&k)){
ll ans = 1;
for(int i = 0; i < cnt && prime[i] <= n; i++){
ans *= (resolve(n,prime[i]) - resolve(k,prime[i]) - resolve(n-k,prime[i]) + 1);
}
printf("%lld\n",ans);
}
return 0;
}