Lucas 应用

主要用来当求C(n,m)%p;  这里的n,m很大,不能用数组表示,而p可以用数组表示时。 

 

hdu:  3037 Saving Beans

题意:

模型是有m + 1个球(0,1,2.....m),放到n个盒子里面,问有多少种方法。 典型的球同,盒不同,不允许空箱 C(n + m + 1 - 1,m + 1 - 1);

思路:
因为这里n,m太大,无法直接求,所以利用Lucas(n,m,p) = C(n%p,m%p)*Lucas(n/p,m/p,p)来求。

 

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")

#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <cstring>

#include <algorithm>

#include <string>

#include <set>

#include <functional>

#include <numeric>

#include <sstream>

#include <stack>

#include <map>

#include <queue>



#define CL(arr, val)    memset(arr, val, sizeof(arr))



#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1



#define ll __int64

#define L(x)    (x) << 1

#define R(x)    (x) << 1 | 1

#define MID(l, r)   (l + r) >> 1

#define Min(x, y)   (x) < (y) ? (x) : (y)

#define Max(x, y)   (x) < (y) ? (y) : (x)

#define E(x)        (1 << (x))

#define iabs(x)     (x) < 0 ? -(x) : (x)

#define OUT(x)  printf("%I64d\n", x)

#define lowbit(x)   (x)&(-x)

#define Read()  freopen("din.txt", "r", stdin)

#define Write() freopen("dout.txt", "w", stdout);





#define M 26

#define N 100007





using namespace std;





const int inf = 0x1F1F1F1F;

const int mod = 1000000007;

const int X = 1000000005;



ll fac[N];

ll n,m,p;



void init()

{

    fac[0] = 1;

    for (int i = 1; i <= p; ++i)

    {

        fac[i] = fac[i - 1]*i%p;

    }

}

ll modexp(ll a,ll b, ll c)

{

    ll rs = 1;

    ll tmp = a%p; //注意这里先要模p

    while (b)

    {

        if (b&1) rs = rs*tmp%c;

        tmp = tmp*tmp%p;

        b >>= 1;

    }

    return rs;

}

ll C(ll x,ll y)

{

    if (y > x) return 0;//注意这里出现访问越界的处理

    ll ans = fac[x]*modexp(fac[y],p - 2,p)%p;

    ans = ans*modexp(fac[x - y],p - 2,p)%p;

    return ans;

}

ll Lucas(ll n,ll m,ll p)

{

    if (m == 0) return 1;

    return (C(n%p,m%p)*Lucas(n/p,m/p,p))%p;

}

int main()

{

    int T;

    scanf("%d",&T);

    while (T--)

    {

        scanf("%I64d%I64d%I64d",&n,&m,&p);

        init();

        printf("%I64d\n",Lucas(n + m,m,p));

    }

    return 0;

}

 

 Lucas 的推广

HDU  4349 Xiao Ming's Hope

题意:

给定n,求C(n,0) ,C(n,1) ...... C(n,n)中存在多少奇数。

思路:

求C(n,m)%2  是否为1即可。看到这个式子我们应该想到Lacus定理,然后想到他的证明,n用2进制表示,然后把每一位取出来计算 假设n = 10010011  m满足什么条件C(n,m)才是奇数呢?很简单,当n的i位为1时,m对应0,1都是(C(1,0) = C(1,1) )1,当n的i位为0时,如果我们取1 C(0,1) = 0那么最终 C(n,m)为偶数,  所以我们只能取0,C(0,0)为1,不影响奇性

 所以我们只要枚举n所对应的的位为1的取0,1即可。

int main()

{

    int n;

    while (~scanf("%d",&n))

    {

        int sum = 0;

        while (n)

        {

            if (n&1) sum++;

            n >>= 1;

        }

        cout<<(1<<sum)<<endl;

    }

    return 0;

}

 

 

你可能感兴趣的:(cas)