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

题目大意:给你两个数,计算出这两个数的组合数之后的真因子个数,题目很简单,单数给出的数据太大,这就变成了一个比较难的题目了,并且这个题还卡你时间,一不小心就会超时,烦人得很,所以我们的办法就是打表,用一个二维数组,存放每一个数的阶乘的素数的个数,第一维放要求的这个数,第二维放这个数下面的素数,其值表示这个数的阶乘下面的所有(即从1到这个数)素数的个数,用分子上同一素数的幂减去分母上同一素数的幂,这样就能计算出来,并且时间不会超时。

代码如下:
 

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
typedef long long ll;
ll prime[500],isprime[500];
ll cnt=0;
ll dis[500][500];
ll vis[500];
void olashai()
{
	for(ll i=2;i<=460;i++)
	{
		if(isprime[i]==0) prime[++cnt]=i;
		for(ll j=1;j<=cnt&&prime[j]*i<440;j++)
		{
			isprime[prime[j]*i]=1;
			if(i%prime[j]==0) break;
		}
	}
}
ll jisuan(ll x)
{
	ll k=x,ans=0;
	for(ll i=1;i<=cnt;i++)
	{
		dis[k][prime[i]]+=vis[prime[i]];
		if(x%prime[i]==0)
		{
			while(x%prime[i]==0)
			{
				vis[prime[i]]+=1;
				dis[k][prime[i]]+=1;
				x/=prime[i];
			}	
		}
	}
	
}
int main()
{
	ll n,m;
	olashai();
	
	memset(vis,0,sizeof(vis));
	memset(dis,0,sizeof(dis));
	for(ll i=1;i<=431;i++)
		jisuan(i);	
	while(~scanf("%lld%lld",&n,&m))
	{
		ll ans=1;
		for(ll i=1;i<cnt;i++)
		{
			ans*=((dis[n][prime[i]]-dis[m][prime[i]]-dis[n-m][prime[i]])+1);
		//	printf("%lld %lld %lld\n",dis[n][i],dis[m][i],dis[n-m][i]);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

革命尚未成功,同志还需努力,加油!!!

猜你喜欢

转载自blog.csdn.net/qq_43916260/article/details/88423813