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
  • 相关阅读:
    Python与mongo交互
    MongoDB数据库操作
    爬虫之xpath解析库
    selenium常用操作
    无头浏览器的使用
    BeautifulSoup库使用
    urllib简单介绍
    爬虫自动化工具防检测
    支付宝支付
    TortoiseSVN使用教程[多图超详细]
  • 原文地址:https://www.cnblogs.com/widsom/p/7692965.html
Copyright © 2011-2022 走看看