• bzoj3129[Sdoi2013]方程 exlucas+容斥原理


    3129: [Sdoi2013]方程

    Time Limit: 30 Sec  Memory Limit: 256 MB
    Submit: 582  Solved: 338
    [Submit][Status][Discuss]

    Description

    给定方程
        X1+X2+. +Xn=M
    我们对第l..N1个变量进行一些限制:
    Xl < = A
    X2 < = A2
    Xn1 < = An1
    我们对第n1 + 1..n1+n2个变量进行一些限制:
    Xn1+l > = An1+1
    Xn1+2 > = An1+2
    Xnl+n2 > = Anl+n2
    求:在满足这些限制的前提下,该方程正整数解的个数。
    答案可能很大,请输出对p取模后的答案,也即答案除以p的余数。

    Input

        输入含有多组数据,第一行两个正整数T,p。T表示这个测试点内的数据组数,p的含义见题目描述。
        对于每组数据,第一行四个非负整数n,n1,n2,m。
        第二行nl+n2个正整数,表示A1..n1+n2。请注意,如果n1+n2等于0,那么这一行会成为一个空行。

    Output

      共T行,每行一个正整数表示取模后的答案。

    Sample Input

    3 10007
    3 1 1 6
    3 3
    3 0 0 5
    3 1 1 3
    3 3

    Sample Output

    3
    6
    0
    【样例说明】
    对于第一组数据,三组解为(1,3,2),(1,4,1),(2,3,1)
    对于第二组数据,六组解为(1,1,3),(1,2,2),(1,3,1),(2,1,2),(2,2,1),(3,1,1)

    HINT

    n < = 10^9  , n1 < = 8   , n2 < = 8   ,  m < = 10^9  ,p<=437367875

    对于l00%的测试数据:  T < = 5,1 < = A1..n1_n2  < = m,n1+n2 < = n

     

    exlucas+容斥啊。
    这道题主要考点是exlucas而不是容斥吧。
    模型转换可以看成向盒子里装小球 ,转化成隔板原理

    而由于组合数C(n,m)中n和m太大了且p不一定是质数,需要用exlucas来求组合数模
    对于有下界限制的,强行先分给它 下界-1个
    对于上界限制的直接容斥 没超的-至少1个超的+至少2个超的..
    exlucas可以翻翻网上博客,主要就用了CRT和快速求阶乘来得到组合数
    代码我懒得写了,复制了别人的

    lucas&&exlucas   https://www.cnblogs.com/candy99/p/6637629.html
    这道题代码原网址:http://blog.csdn.net/werkeytom_ftd/article/details/50152143

    #include<cstdio>
    #include<iostream>
    #define fo(i,a,b) for(i=a;i<=b;i++)
    using namespace std;
    typedef long long ll;
    ll f[10],a[20],b[20],c[20],d[20],e[20],pri[32000+10],fac[100000+10];
    bool bz[32000+10];
    ll i,j,k,l,t,n,m,n1,n2,ca,p,pp,num,top,xx,yy,cnt;
    ll quicksortmi(ll x,ll y,ll p){
        if (!y) return 1;
        if (y==1) return x%p;
        ll t=quicksortmi(x,y/2,p);
        t=t*t%p;
        if (y%2) t=t*(x%p)%p;
        return t;
    }
    void gcd(ll a,ll b){
        if (!b){
            xx=1;
            yy=0;
        }
        else{
            gcd(b,a%b);
            swap(xx,yy);
            yy-=xx*(a/b);
        }
    }
    ll getny(ll x,ll y){
        gcd(x,y);
        xx=(xx%y+y)%y;
        return xx;
    }
    ll calcfac(ll n,ll p,ll pp){
        if (n<pp) return fac[n];
        ll t=quicksortmi(fac[p-1],n/p,p);
        t=t*fac[n%p]%p;
        cnt+=n/pp;
        t=t*calcfac(n/pp,p,pp)%p;
        return t;
    }
    ll calc(ll x,ll y,ll p,ll pp){
        ll i;
        fac[0]=1;
        fo(i,1,p-1)
            if (i%pp==0) fac[i]=fac[i-1];
            else fac[i]=fac[i-1]*i%p;
        cnt=0;
        ll A=calcfac(y,p,pp);
        ll tot=cnt;
        cnt=0;
        ll B=calcfac(x,p,pp);
        B=B*calcfac(y-x,p,pp)%p;
        B=getny(B,p);
        return A*B%p*quicksortmi(pp,tot-cnt,p)%p;
    }
    ll comb(ll x,ll y,ll p){
        if (x>y) return 0;
        fo(i,1,top) a[i]=calc(x,y,d[i],e[i]);
        fo(i,1,top) b[i]=getny(c[i],d[i]);
        ll t=0;
        fo(i,1,top) t=(t+a[i]*b[i]%p*c[i]%p)%p;
        return t;
    }
    void dfs(ll x,ll m,ll cnt){
        if (x==n1+1){
            ll t=comb(n-1,m-1,p);
            if (cnt%2) num=((num-t)%p+p)%p;
            else num=(num+t)%p;
            return;
        }
        dfs(x+1,m,cnt);
        if (m-f[x]) dfs(x+1,m-f[x],cnt+1);
    }
    int main(){
        fo(i,2,32000){
            if (!bz[i]) pri[++k]=i;
            fo(j,1,k){
                if (pri[j]*i>32000) break;
                bz[i*pri[j]]=1;
                if (i%pri[j]==0) break;
            }
        }
        scanf("%lld%lld",&ca,&p);
        pp=p;
        fo(i,1,k){
            if (pp%pri[i]==0){
                d[++top]=1;e[top]=pri[i];
                while (pp%pri[i]==0){
                    d[top]*=pri[i];
                    pp/=pri[i];
                }
            }
        }
        fo(i,1,top) c[i]=p/d[i];
        while (ca--){
            scanf("%lld%lld%lld%lld",&n,&n1,&n2,&m);
            fo(i,1,n1) scanf("%lld",&f[i]);
            fo(i,1,n2){
                scanf("%lld",&k);
                if (k) m-=k-1;
            }
            num=0;
            dfs(1,m,0);
            printf("%lld
    ",num);
        }
    }
  • 相关阅读:
    H5本地存储
    小知识(h5 js )
    在ubuntu18.04版本安装vscode
    函数基本操作
    python直接赋值、深浅拷贝实例剖析
    collections模块简介
    set()集合基本操作
    list、tuple、dict内部功能释义
    str内部方法释义
    int内部方法释义
  • 原文地址:https://www.cnblogs.com/wsy01/p/8039585.html
Copyright © 2020-2023  润新知