zoukankan      html  css  js  c++  java
  • 算法笔记--卢卡斯定理

    Lucas定理是用来(当n和m和p很大时)求 C(n,m) mod p,p为素数的值。

    表达式:C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p。(可以递归)

    递归方程:(C(n%p, m%p)*Lucas(n/p, m/p))%p。(递归出口为m==0,return 1)

    模板:

    const int N=1e5+7;
    int p;
    ll fac[N];
    void init()
    {
        fac[0]=1;
        for(int i=1;i<=p;i++)fac[i]=fac[i-1]*i%p;
    } 
    ll q_pow(ll n,ll k)
    {
        ll ans=1;
        while(k)
        {
            if(k&1)ans=ans*n%p;
            n=n*n%p;
            k>>=1;
        }
        return ans;
    }
    ll C(ll n,ll m)
    {
        if(m>n)return 0;
        return fac[n]*q_pow(fac[m]*fac[n-m]%p,p-2)%p; 
    } 
    ll lucas(ll n,ll m)
    {
        if(m==0)return 1;
        return (C(n%p,m%p)*lucas(n/p,m/p))%p;
    }

    例题1:451E - Devu and Flowers

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define pi acos(-1.0)
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e5+7;
    int p;
    ll fac[N];
    ll f[25];
    void init()
    {
        fac[0]=1;
        for(int i=1;i<=p;i++)fac[i]=fac[i-1]*i%p;
    } 
    ll q_pow(ll n,ll k)
    {
        ll ans=1;
        while(k)
        {
            if(k&1)ans=ans*n%p;
            n=n*n%p;
            k>>=1;
        }
        return ans;
    }
    ll C(ll n,ll m)
    {
        if(n<m)return 0;
        if(n-m<m)m=n-m;
        ll s1=1,s2=1;
        for(int i=0;i<m;i++) 
        {
            s1=s1*(n-i)%p;
            s2=s2*(i+1)%p;
        }
        return s1*q_pow(s2,p-2)%p;
    } 
    ll lucas(ll n,ll m)
    {
        if(m==0)return 1;
        return (C(n%p,m%p)*lucas(n/p,m/p))%p;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        p=1e9+7;
        ll n,s;
        cin>>n>>s;
        for(int i=0;i<n;i++)cin>>f[i];
        ll ans=0;
        for(int i=0;i<(1<<n);i++)
        {
            ll sum=s,sign=1;
            for(int j=0;j<n;j++)
            {
                if(i&(1<<j))
                {
                    sum-=f[j]+1;
                    sign=-sign;
                }
            }
            if(sum<0)continue;
            ans+=sign*lucas(sum+n-1,n-1);
            ans%=p;
        }
        cout<<(ans+p)%p<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    java 面向对象(十八):包装类的使用
    java 面向对象(十七):单元测试方法
    rxjava2学习
    多线程-wait(),notify(),notifyAll()
    多线程-Thread.join()的运用
    66. Plus One
    理解Android View的事件传递机制
    78. Subsets
    程序员学习与成长的方法(转发)
    android查询天气demo,基于mvp+kotlin+rxjava2+retrofit2
  • 原文地址:https://www.cnblogs.com/widsom/p/7692965.html
Copyright © 2011-2022 走看看