您的位置:首页 > 其它

[Lucas定理] hdu 3037 Saving Beans

2014-11-08 17:02 429 查看
摘自大牛:cxlove

Lucas 定理:A、B是非负整数,p是质数。AB写成p进制:A=a
a[n-1]...a[0],B=b
b[n-1]...b[0]。

则组合数C(A,B)与C(a
,b
)*C(a[n-1],b[n-1])*...*C(a[0],b[0]) modp同

即:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p)

For non-negative integers m and n and a prime p, the following congruence
relation holds:

where

and

are the base p expansions of m and n respectively.

首先我们注意到 n=(ak...a2,a1,a0)p = (ak...a2,a1)p * p + a0

= [n/p]*p+a0

且m=[m/p]+b0

只要我们更够证明 C(n,m)=C([n/p],[m/p]) * C(a0,b0) (mod p)

剩下的工作由归纳法即可完成

我们知道对任意质数p: (1+x)^p == 1+(x^p) (mod p)

注意!这里一定要是质数 ................(为什么)

对 模p 而言

上式左右两边的x^m的系数对模p而言一定同余(为什么),其中左边的x^m的系数是 C(n,m) 而由于a0和b0都小于p

右边的x^m ( = x^(([m/p]*p)+b0)) 一定是由 x^([m/p]*p) 和 x^b0 相乘而得 (即发生于 i=[m/p] , j=b0 时) 因此我们就有了

C(n,m)=C([n/p],[m/p]) * C(a0,b0) (mod p)

HDU 3037

http://acm.hdu.edu.cn/showproblem.php?pid=3037

基本的组合数学,C(N+M,M)然后对P取模

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"stack"
#include"algorithm"
#include"iostream"
using namespace std;
#define ll __int64
ll mod;
ll power(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans%mod;
}
ll fc(ll n,ll m)
{
    if(m>n) return 0;
    ll t1,t2;
    t1=t2=1;
    for(ll i=n; i>m; i--)
    {
        t1=(t1*i)%mod;
        t2=(t2*(i-m))%mod;
    }
    return (t1*power(t2,mod-2))%mod;
}

ll lucas(ll n,ll m,ll mod)
{
    if(m==0) return 1;
    ll ans;
    ans=fc(n%mod,m%mod);
    return (ans*lucas(n/mod,m/mod,mod))%mod;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll n,m;
        scanf("%I64d%I64d%I64d",&n,&m,&mod);
        printf("%I64d\n",lucas(n+m,m,mod));
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: