题意:求组合数C(n, k)的约数的个数 (0 ≤ k ≤ n ≤ 431)。
题目链接:http://poj.org/problem?id=2992
——>>3个公式:
1、n!中含素数p的个数为n/p + n/p^2 + n/p^3 + ...(到0停)程序中通过cal函数实现
2、C(n, k) = n! / (n-k)! / k!
3、n = p1^a1*p2^a2*...*pk^ak约数的个数为(a1+1)(a2+1)...(ak+1)
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn = 431 + 10;
int p[maxn], m;
long long C[maxn][maxn];
void prime_table() //筛法素数打表
{
bool vis[maxn];
int i, j;
memset(vis, 0, sizeof(vis));
for(i = 2; i <= 431; i++)
if(!vis[i]) for(j = (i<<1); j <= 431; j += i) vis[j] = 1;
m = 0;
for(i = 2; i <= 431; i++)
if(!vis[i]) p[m++] = i;
}
long long cal(int n, int pri) //n!含素数pri的个数
{
return (n < pri) ? 0 : (n/pri + cal(n/pri, pri));
}
int main()
{
int n, k, i;
prime_table();
while(~scanf("%d%d", &n, &k))
{
long long sum = 1;
for(i = 0; i < m; i++) sum *= (cal(n, p[i])-cal(n-k, p[i])-cal(k, p[i])+1);
printf("%I64d\n", sum);
}
return 0;
}