组合数取模(0)

来源:互联网 发布:淘宝卖家手机端装修 编辑:程序博客网 时间:2024/06/17 12:04

直接采用公式C(n m)=n!/m!(n-m)!

#include<stdio.h>

typedef long long ll;
ll factorial(ll x)
{
if(x==0)
{
return 1;
}
return x*factorial(x-1);
}


int main()
{
ll n,m,p;
while(scanf("%lld %lld %lld",&n,&m,&p)!=EOF)
{
printf("%lld",factorial(n)/(factorial(n-m)*factorial(m))%p);
}
return 0;

这样做阶乘预处理,会很容易溢出

改进:既然一口气处理阶乘会溢出,那么可以一边×一边÷,但是有可能会遇到无法整除的情况,那么可以借用double+ceil()向上取整函数

#include<stdio.h>
#include<math.h>
typedef long long ll;
ll p; 


int main()
{
ll n,m;
double x=1;
while(scanf("%lld %lld %lld",&n,&m,&p)!=EOF)
{
while(m)
{
x*=(n-m+1);
x/=m;
m--;
}
printf("%lld\n",(long long)ceil(x)%p);
}
return 0;

虽然方法可是适当扩大n,m的取值上限,但是也不能称之为一个特别好的方法,毕竟double与整形、长整形之间的强转存在着误差,但是可以想见,一边乘一边除不失为一个好方法,但是如何避免使用强转带来的误差呢。

此处给出一个定理,所有的数都可以分解为几个素数之积。

代码有空贴出。


原创粉丝点击