zoukankan      html  css  js  c++  java
  • [十二省联考2019]皮配

    [十二省联考2019]皮配 

    巧妙运用“独立”的性质,对于“不独立”的进行暴力处理,再合并

    1.dp[i][j][k]前i个城市,蓝有j,鸭有k个方案数

    2.无限制时,城市的阵营和学校的派系独立,直接Dp出城市选择方案,派系选择方案,直接乘起来。显然唯一分配且一一对应

    有限制,只有30个

    考虑对于有限制的城市,优先考虑这些城市的阵营和这个城市中学校的派系分配。

    f[i][j][k],前i个有限制的城市,“总共学校占蓝色阵营j个”,有限制的学校占鸭k个

    对于没有限制的,

    g[i][j]前i个无限制城市,占蓝色阵营j个,

    h[i][j]前i个无限制学校,占鸭派系j个

    最后枚举j,k,处理出g,h的取值范围,然后乘起来就是方案

    考虑每个答案会被统计的位置,显然还是一一对应的。

    注意:

    1.取mod

    2.区间下界可能<0,

    3.是“总共学校占蓝色阵营j个”!!!!!!而不是仅考虑限制城市中的限制学校。

    mdzz

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define solid const auto &
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int M=2503;
    const int N=1003;
    const int mod=998244353;
    int n,m,c,K;
    int f[M][M],g[M],h[M],p[M][M],q[M][M],s[N];
    int b[N];
    int C0,C1,D0,D1;
    vector<int>city[N];
    // int sz[N];
    int no[N],has[N];
    int ad(int x,int y){
        return x+y>=mod?x+y-mod:x+y;
    }
    void cpy(int f[M][M],int g[M][M],int a,int b){
        for(reg i=0;i<=a;++i){
            for(reg j=0;j<=b;++j){
                f[i][j]=g[i][j];
            }
        }
    }
    void clear(){
        memset(f,0,sizeof f);
        memset(h,0,sizeof h);
        memset(g,0,sizeof g);
        memset(has,0,sizeof has);
        // memset(sz,0,sizeof sz);
        memset(no,-1,sizeof no);
        for(reg i=1;i<=n;++i){
            city[i].clear();
        }
    }
    int main(){
        int t;rd(t);
        while(t--){
            clear();
            rd(n);rd(c);
            rd(C0);rd(C1);rd(D0);rd(D1);
            int sum=0;
            for(reg i=1;i<=n;++i){
                rd(b[i]);rd(s[i]);sum+=s[i];
                has[b[i]]+=s[i];
                // city[b[i]].push_back(i);
            }
            // memset(no,-1,sizeof no);
            // memset(sz,0,sizeof sz);
            // memset(has,0,sizeof has);
            rd(K);
            int x;
            for(reg i=1;i<=K;++i){
                rd(x);rd(no[x]);
                city[b[x]].push_back(x);
                // sz[b[x]]+=s[x];
            }
            f[0][0]=1;
            int now=0;
            for(reg o=1;o<=c;++o){
                if(city[o].size()==0) continue;
                int sum1=min(C0,now+has[o]);
                int sum2=min(D0,now+has[o]);
                // cout<<" sum1 "<<sum1<<" "<<sum2<<endl;
                cpy(p,f,sum1,sum2);
                // sum1=min(C0,now);sum2=min(D0,now);
                for(auto id:city[o]){//C0
                    // sum1=min(C0,sum1+has[id]);
                    // sum2=min(D0,sum2+has[id]);
                    for(reg i=sum1;i>=0;--i){
                        for(reg j=sum2;j>=0;--j){
                            int lp=p[i][j];
                            p[i][j]=0;
                                if(no[id]!=0){
                                    p[i][j]=ad(p[i][j],p[i][j-s[id]]);
                                }
                                if(no[id]!=1){
                                    p[i][j]=ad(p[i][j],lp);
                                }
                        }
                    }
                }
                // cout<<" sum1 "<<sum1<<" sum "<<sum2<<endl;
                for(reg i=sum1;i>=0;--i){
                    for(reg j=sum2;j>=0;--j){
                        p[i][j]=0;
                        if(i>=has[o]) {
                            // cout<<" hahah "<<o<<" "<<p[i-has[o]][j]<<endl;
                            p[i][j]=p[i-has[o]][j];
                        }
                    }
                }
                cpy(q,f,sum1,sum2);
                sum1=min(C0,now+has[o]);
                sum2=min(D0,now+has[o]);
                for(auto id:city[o]){//C1
                    // sum1=min(C0,sum1+has[id]);
                    // sum2=min(D0,sum2+has[id]);
                    for(reg i=sum1;i>=0;--i){
                        for(reg j=sum2;j>=0;--j){
                            int lp=q[i][j];
                            q[i][j]=0;
                            // if(i>=s[id]){
                            if(j>=s[id]&&no[id]!=2){
                                q[i][j]=ad(q[i][j],q[i][j-s[id]]);
                            }
                            if(no[id]!=3){
                                q[i][j]=ad(q[i][j],lp);
                            }
                            // }
                        }
                    }
                }
    
                for(reg i=0;i<=sum1;++i){
                    for(reg j=0;j<=sum2;++j){
                        f[i][j]=ad(p[i][j],q[i][j]);
                    }
                }
                now+=has[o];
            }
            // for(reg i=0;i<=C0;++i){
            //     for(reg j=0;j<=D0;++j){
            //         cout<<i<<" "<<j<<" : "<<f[i][j]<<endl;
            //     }
            // }cout<<endl;
    
            g[0]=1;
            int S=0;
            for(reg i=1;i<=c;++i){
                if(city[i].size()) continue;
                if(!has[i]) continue;
                S=min(C0,S+has[i]);
                for(reg j=S;j>=0;--j){
                    if(j>=has[i]) g[j]=ad(g[j-has[i]],g[j]);
                }
            }
            h[0]=1;
            S=0;
            for(reg i=1;i<=n;++i){
                if(no[i]!=-1) continue;
                S=min(D0,S+s[i]);
                for(reg j=S;j>=0;--j){
                    if(j>=s[i]) h[j]=ad(h[j-s[i]],h[j]);
                }
            }
            // prt(g,0,C0);
            // prt(h,0,D0);
            for(reg i=1;i<=C0;++i) g[i]=ad(g[i],g[i-1]);
            for(reg i=1;i<=D0;++i) h[i]=ad(h[i],h[i-1]);
            ll ans=0;
            for(reg i=0;i<=C0;++i){
                for(reg j=0;j<=D0;++j){
                    int l1=sum-i-C1-1,h1=C0-i;
                    int l2=sum-j-D1-1,h2=D0-j;
                    if(l1>=h1||l2>=h2) continue;
                    // if((ll)f[i][j]*ad(g[h1],mod-g[l1])%mod*ad(h[h2],mod-h[l2])) {
                    //     cout<<" i "<<i<<" j "<<j<<" con "<<(ll)f[i][j]*ad(g[h1],mod-g[l1])%mod*ad(h[h2],mod-h[l2])<<endl;
                    //     cout<<" nc "<<f[i][j]<<" g1 "<<ad(g[h1],mod-g[l1])<<" h1 "<<ad(h[h2],mod-h[l2])<<endl;
                    //     cout<<endl;
                    // }
                    ans=ad(ans,(ll)f[i][j]*ad(g[h1],mod-((l1>=0)?g[l1]:0))%mod*ad(h[h2],mod-((l2>=0)?h[l2]:0))%mod);
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */
  • 相关阅读:
    单表查询
    解读python中SocketServer源码
    C++实训(2.3)
    C++实训(2.2)
    C++实训(2.1)
    C++实训(1.3)
    C++实训(1.1)
    顺序表的实现,在vs2019上运行成功
    p243_5(3)
    自考新教材-p176_5(2)
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10771520.html
Copyright © 2011-2022 走看看