题目链接:http://poj.org/problem?id=2992
题目大意:就是叫你求组合数C(n,m)的因子的个数。
思路:求解这题需要用到以下几个定理
1、对任意的n,可以这么表示 n=p1^e1*p2^e2*p3*e3*......pn^en 。(p1,p2,p3......pn都为素数)
2、对任意的n的因子数为:(1+e1)*(1+e2)*(1+e3)*......*(1+en)
3、n!的素数因子=(n-1)!的素数因子+n的素数因子
4、C(n,k)的素因子=n!的素因子 - (n-k)!的素因子 - k!的素因子
有了上面介绍的几个定理那么这题就比较好解啦。。。。
code:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int a[450][450],b[450]; //a[i][j] 表示 i!中的素因子j的出现的次数
int prime[450],vis[450];
int len;
int primetable() //打印素数表
{
int i,j;
int c=0;
memset(vis,0,sizeof(vis));
for(i=2;i<=431;i++)
{
if(!vis[i])
{
prime[c++]=i;
for(j=i*i;j<=431;j+=i)
{
vis[j]=1;
}
}
}
return c;
}
void f() //计算2!到431!中的每个数中的素因子的出现的次数
{
int i,j;
memset(a,0,sizeof(a));
for(i=2;i<=431;i++)
{
int ii=i;
memcpy(a[i],a[i-1],sizeof(a[i])); //把a[i-1]中的各元素拷贝到a[i]中
for(j=0;j<len;j++)
{
if(prime[j]>ii) break;
if(ii%prime[j]==0)
{
int sum=0;
while(ii%prime[j]==0)
{
sum++;
ii/=prime[j];
}
a[i][prime[j]]+=sum;
}
}
}
}
int main()
{
int n,k,i,j;
len=primetable();
f();
while(scanf("%d%d",&n,&k)==2)
{
memcpy(b,a[n],sizeof(a[n]));
__int64 cnt=1; //cnt用__int64,其他的变量用int就行啦
for(i=0;i<=431;i++)
{
b[i]=b[i]-a[k][i]-a[n-k][i];
cnt*=(1+b[i]);
}
printf("%I64d\n",cnt);
}
return 0;
}