题目链接:
https://cn.vjudge.net/problem/POJ-2992
题目大意:
给出组合数C,求出其因子个数,其中n,k不大于431,组合数的值在long long范围内
解题思路:
由于只有431种阶乘,先预处理431中素数,再预处理出每一个阶乘里面所含的素因子的指数,然后对于组合数,直接用素因子指数相减即可。
求出的质因子指数,就可以用定理直接求因子个数。
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
bool not_prime[];
int prime[], tot;
void sieve(int n)
{
for(int i = ; i <= n; i++)
if(!not_prime[i])
{
prime[tot++] = i;
for(int j = i * ; j <= n; j += i)
not_prime[j] = ;
}
}
int a[][];//a[i][j]表示i的阶乘中素数prime[j]的指数
void init(int n)
{
for(int i = ; i <= n; i++)
{
for(int j = ; j < tot && prime[j] <= n; j++)
{
if(i % prime[j] == )
{
int t = i;
while(t % prime[j] == )
{
t /= prime[j];
a[i][j]++;
}
}
a[i][j] += a[i - ][j];
}
}
/*for(int i = 1; i <= 50; i++)
{
for(int j = 0; j < tot; j++)
{
if(a[i][j])
{
printf("%d %d %d\n", i, prime[j], a[i][j]);
}
}
}*/
}
int main()
{
sieve();
init();
int n, k;
while(scanf("%d%d", &n, &k) != EOF)
{
int ant[];
for(int i = ; i < tot; i++)
ant[i] = a[n][i] - a[k][i] - a[n - k][i];
ll ans = ;
for(int i = ; i < tot; i++)
ans *= (ant[i] + );
printf("%lld\n", ans);
}
return ;
}