[十二省联考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*
*/
原文地址:https://www.cnblogs.com/Miracevin/p/10771520.html