Divisors
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 11983 | Accepted: 3575 |
Description
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
Source
【思路】
要求一个较大组合数的因数个数,所以要对这个组合数进行质因数分解,分解成p1^r1*p2^r2*p3^r3*...*pm^rm(其中pi为质因数,ri为该质因数对应的次数),最后答案就是(r1+1)*(r2+1)*(r3+1)*...*(rm+1)。因为组合数C(n,k)等于n!/[(k!)*(n-k)!],所以问题就化成了对三个部分进行质因数分解,再把幂次情况汇总起来就好了。
【代码】
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=500;
int total,n,k;
int prime[MAXN+10],num[MAXN];
bool boolprime[MAXN+10];
void euler(int n)
{
memset(boolprime,false,sizeof(boolprime));
total=0;
for(int i=2;i<=n;i++){
if(!boolprime[i])prime[++total]=i;
for(int j=1;j<=total&&i*prime[j]<=n;j++){
boolprime[i*prime[j]]=true;
if(i%prime[j]==0)break;
}
}
}
void add(int mes,int n)
{
for(int i=1;i<=total&&prime[i]<=n;i++){
int tmp=prime[i];
while(tmp<=n){
if(mes==1)
num[i]+=n/tmp;
else
num[i]-=n/tmp;
tmp*=prime[i];
}
}
}
int main()
{
euler(431);
while(scanf("%d %d",&n,&k)==2){
memset(num,0,sizeof(num));
add(1,n);
add(0,k);
add(0,n-k);
long long ans=1;
for(int i=1;i<=total;i++)
ans*=(num[i]+1);
printf("%lld\n",ans);
}
return 0;
}