【洛谷 P5289】【十二省联考】—皮配(背包dp)

传送门

分成三类
不受影响的城市以及城市的学校
受影响的城市里不受影响的学校
受影响的学校

第一类可以直接O(nc)O(nc)分别dpdp阵营和派系后乘起来
第二类可以和第一类一起dpdp派系但不考虑阵营
第三类暴力O(kc2)dpO(kc^2)dp即可

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
#define poly vector<int>  
cs int mod=998244353;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline void Mul(int &a,int b){a=1ll*a*b%mod;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=1005,M=2505;
int n,c,c0,c1,d0,d1,K;
int bel[N],val[N],s[N],sum[N],req[N],ban[N],vis[N];
vector<int> lim[N],city,sco;
int f[M],g[M],p[M][M],tp1[M][M],tp2[M][M];
inline void calc_p(){
	int tot1=0,tot2=0,r1=0,r2=0;
	p[0][0]=1;
	for(int o=1;o<=c;o++){
		if(!lim[o].size())continue;
		for(int i=min(tot1,c0);~i;i--)
		for(int j=min(tot2,d0);~j;j--)
		tp1[i][j]=tp2[i][j]=p[i][j];
		for(int &x:lim[o]){
			tot2+=val[x];
			int t0=ban[x]!=0,t1=ban[x]!=1,t2=ban[x]!=2,t3=ban[x]!=3;
			for(int i=min(tot1,c0);~i;i--)
			for(int j=min(tot2,d0);~j;j--)
			if(j>=val[x]){
				tp1[i][j]=add(tp1[i][j]*t1,tp1[i][j-val[x]]*t0);
				tp2[i][j]=add(tp2[i][j]*t3,tp2[i][j-val[x]]*t2);
				chemx(r1,i),chemx(r2,j);
			}
			else tp1[i][j]=tp1[i][j]*t1,tp2[i][j]=tp2[i][j]*t3,chemx(r1,i),chemx(r2,j);;
		}
		tot1+=sum[o];
		for(int i=min(tot1,c0);~i;i--)
		for(int j=min(tot2,d0);~j;j--)
		if(i>=sum[o])p[i][j]=add(tp1[i-sum[o]][j],tp2[i][j]),chemx(r1,i),chemx(r2,j);
		else p[i][j]=tp2[i][j],chemx(r1,i),chemx(r2,j);;
	}
	for(int i=min(tot1,c0);~i;i--)
	memset(tp1[i],0,sizeof(int)*(min(tot2,d0)+1)),memset(tp2[i],0,sizeof(int)*(min(tot2,d0)+1));
}
inline void calc_f(){
	memset(f,0,sizeof(int)*(c0+1));
	f[0]=1;int tot=0,res;
	for(int &x:city){
		tot+=x;
		for(int j=min(c0,tot);~j;j--){
			res=0;
			if(j>=x)Add(res,f[j-x]);
			if(tot-j<=c1)Add(res,f[j]);
			f[j]=res;
		}
	}
}
inline void calc_g(){
	memset(g,0,sizeof(int)*(d0+1));
	g[0]=1;int tot=0,res;
	for(int &x:sco){
		tot+=x;
		for(int j=min(d0,tot);~j;j--){
			res=0;
			if(j>=x)Add(res,g[j-x]);
			if(tot-j<=d1)Add(res,g[j]);
			g[j]=res;
		}
	}
}
inline void solve(){
	n=read(),c=read();int tot=0;
	c0=read(),c1=read(),d0=read(),d1=read();
	for(int i=1;i<=n;i++)
		bel[i]=read(),val[i]=read(),tot+=val[i],sum[bel[i]]+=val[i];
	K=read();
	for(int i=1;i<=K;i++){
		int pos=read(),r=read();
		req[bel[pos]]=1,ban[pos]=r,vis[pos]=1;
		lim[bel[pos]].pb(pos);
	}
	for(int i=1;i<=n;i++)if(!vis[i])s[bel[i]]+=val[i],sco.pb(val[i]);
	for(int i=1;i<=c;i++)if(!req[i]&&s[i])city.pb(s[i]);
	calc_f();
	calc_g();
	calc_p();
	int res=0;
	for(int i=1;i<=c0;i++)Add(f[i],f[i-1]);
	for(int i=1;i<=d0;i++)Add(g[i],g[i-1]);
	for(int i=0;i<=c0;i++)
	for(int j=0;j<=d0;j++){
		int tmp=1;
		if(c0-i>=tot-c1-i)Mul(tmp,dec(f[c0-i],tot-c1-i-1>=0?f[tot-c1-i-1]:0));
		if(d0-j>=tot-d1-j)Mul(tmp,dec(g[d0-j],tot-d1-j-1>=0?g[tot-d1-j-1]:0));
		Add(res,mul(tmp,p[i][j]));
	}
	cout<<res<<'\n';
	memset(p,0,sizeof(p));
	for(int i=1;i<=n;i++)vis[i]=val[i]=bel[i]=ban[i]=0;
	for(int i=1;i<=c;i++)sum[i]=s[i]=req[i]=0,lim[i].clear();
	sco.clear(),city.clear();
}
int main(){
	int T=read();
	while(T--)solve();
}
posted @ 2019-09-20 13:00  Stargazer_cykoi  阅读(146)  评论(0编辑  收藏  举报