zoukankan      html  css  js  c++  java
  • ZOJ 3557 & BZOJ 2982 combination[Lucas定理]

    How Many Sets II

    Time Limit: 2 Seconds      Memory Limit: 65536 KB

    Given a set S = {1, 2, ..., n}, number m and p, your job is to count how many set T satisfies the following condition:

    • T is a subset of S
    • |T| = m
    • T does not contain continuous numbers, that is to say x and x+1 can not both in T

    Input

    There are multiple cases, each contains 3 integers n ( 1 <= n <= 109 ), m ( 0 <= m <= 104m <= n ) and p ( p is prime, 1 <= p <= 109 ) in one line seperated by a single space, proceed to the end of file.

    Output

    Output the total number mod p.


    Lucas定理p为质数情况裸题

    因为是选的元素不能连续,我们先把选的元素拿出来,剩下的元素有n-m+1个空,选m个插进去行了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    ll n,m,P;
    ll Pow(ll a,ll b){
        ll ans=1;
        for(;b;b>>=1,a=a*a%P)
            if(b&1) ans=ans*a%P;
        return ans;
    }
    ll Inv(ll a){return Pow(a,P-2);}
    ll C(ll n,ll m){
        if(n<m) return 0;
        ll x=1,y=1;
        for(ll i=n-m+1;i<=n;i++) x=x*i%P;
        for(ll i=1;i<=m;i++) y=y*i%P;
        return x*Inv(y)%P;
    }
    ll Lucas(ll n,ll m){
        if(n<m) return 0;
        ll re=1;
        for(;m;n/=P,m/=P) re=re*C(n%P,m%P)%P;
        return re;
    }
    int main(){
        //freopen("in","r",stdin);
        while(scanf("%lld%lld%lld",&n,&m,&P)!=EOF)
            printf("%lld
    ",Lucas(n-m+1,m));
    }

     BZOJ 2982: combination

    模数10007很小,可以直接线性预处理阶乘和逆元,48ms-->4ms

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=10007;
    inline ll read(){
        char c=getchar();ll x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    ll n,m,P=10007;
    ll inv[N],fac[N],facInv[N];
    void getInv(int n){
        inv[1]=fac[0]=facInv[0]=1;
        for(int i=1;i<=n;i++){
            if(i!=1) inv[i]=-P/i*inv[P%i]%P;
               inv[i]+=inv[i]<0?P:0;
            fac[i]=fac[i-1]*i%P;
            facInv[i]=facInv[i-1]*inv[i]%P;
        }
    }
    
    ll C(ll n,ll m){
        if(n<m) return 0;
        return fac[n]*facInv[m]%P*facInv[n-m]%P;
    }
    ll Lucas(ll n,ll m){
        if(n<m) return 0;
        ll re=1;
        for(;m;n/=P,m/=P) re=re*C(n%P,m%P)%P;
        return re;
    }
    int main(){
        freopen("in","r",stdin);
        getInv(N-1);
        int T=read();
        while(T--){
            n=read();m=read();
            printf("%lld
    ",Lucas(n,m));
        }
    }
  • 相关阅读:
    面试整理之DOM事件阶段
    头疼的闭包
    Bootstrap学习
    旁门左道通过JS与纯CSS实现显示隐藏层
    关于setTimeout的妙用前端函数节流
    兼容古董级IE小结
    Mongodb配置:error:10061 由于目标计算机积极拒绝,无法连接
    webpack入门前端必备
    团队成员的分应该怎么分?
    Start
  • 原文地址:https://www.cnblogs.com/candy99/p/6400213.html
Copyright © 2011-2022 走看看