【动态规划】皮配

110 阅读6分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情

[十二省联考 2019] 皮配

题目背景

一年一度的综艺节目《中国好码农》又开始了。本季度,好码农由 Yazid、Zayid、小 R、大 R 四位梦想导师坐镇,他们都将组建自己的梦想战队,并率领队员向梦想发起冲击。

四位导师的派系不尽相同,节目组为了营造看点,又将导师分成了不同的阵营,与此同时对不同阵营、不同派系都作出了战队总人数限制:

  • 四位导师分成两个阵营
    • Yazid、小 R 两位导师组成蓝阵营,他们两位的战队人数总和不得超过 C0C_0
    • Zayid、大 R 两位导师组成红阵营,他们两位的战队人数总和不得超过 C1C_1
  • 四位导师分成两个派系
    • Yazid、Zayid 两位导师属于鸭派系,他们两位的战队人数总和不得超过 D0D_0
    • 小 R、大 R 两位导师属于 R 派系,他们两位的战队人数总和不得超过 D1D_1

题目描述

本季好码农邀请到了全国各路学生精英参赛。他们来自全国 cc 个城市的 nn 所不同学校(城市的编号从 11cc,学校的编号从 11nn)。其中,第 ii 所学校所属的城市编号为 bib_i,且共有 sis_i 名选手参赛。

在【题目背景】中提到的各总人数限制之外,本季度《中国好码农》的导师选择阶 段有额外规则如下:

  • 来自同城市的所有选手必须加入相同的阵营
  • 来自同学校的所有选手必须选择相同的导师

对于导师,大部分学校的学生对导师没有偏好。但是有 kk 所学校,其中每所学校的学生有且仅有一位他们不喜欢的导师。同一所学校的学生不喜欢的导师相同,他们不会加入他们不喜欢的导师的战队

面对琳琅满目的规则和选手的偏好,作为好码农忠实观众的你想计算出,在所有选 手都进行了战队选择后,战队组成共有多少种可能的局面?

  • 两种战队组成的局面被认为是不同的,当且仅当在存在一所学校,使得在这两种 局面中这所学校的选手加入了不同导师的战队。
  • 由于答案可能很大,你只需输出可能局面数对 998244353998244353 取模的结果即可。

输入格式

单个测试点中包含多组数据,输入的第一行包含一个非负整数 TT 表示数据组数。接下来依次描述每组数据,对于每组数据:

  • 1122 个正整数 nn, cc,分别表示学校数目、城市数目。
  • 2244 个正整数 C0C_0, C1C_1, D0D_0, D1D_1,分别表示题目中所描述的四个限制。
  • 接下来 nn 行每行 22 个正整数:
    • 这部分中第 ii 行的两个数依次为 bib_i, sis_i,分别表示第 ii 所学校的所属城市以及选手数目。
    • 保证 bicb_i \leqslant csimin{M,10}s_i \leqslant\min\left\{M, 10\right\}。其中 M=max{C0,C1,D0,D1}M = \max \left\{C_0, C_1, D_0, D_1\right\}
  • 接下来 11 行一个非负整数 kk,表示选手有偏好的学校数目。
  • 接下来 kk 行,每行 22 个整数 ii, pp,描述编号为 ii 的学校选手有偏好:
    • 其中,pp 为一个 0033 之间的整数,描述该校选手不喜欢的导师:00 代表 Yazid,11 代表小 R,22 代表 Zayid,33 代表大 R。
    • 保证 1in1 \leqslant i \leqslant n,且各行的 ii 互不相同。

对于输入的每一行,如果其包含多个数,则用单个空格将它们隔开。

输出格式

依次输出每组数据的答案,对于每组数据:

  • 一行一个整数,表示可能局面数对 998244353998244353 取模的结果。

样例 #1

样例输入 #1

2
2 1
3 2 2 2
1 1
1 2
1
1 0
4 2
10 30 20 30
1 6
2 4
1 7
2 4
2
2 3
3 1

样例输出 #1

1
22

提示

样例 1 解释

对于第 11 组数据:

  • 唯一的城市 11 包含共 33 名选手,但红阵营的总人数限制为 22,无法容纳这些选手,因此他们被迫只能选择蓝阵营。
  • 在此基础上,由于 11 号学校的选手不喜欢 Yazid 老师,因此他们就必须加入 R 派系的小 R 老师麾下。
  • 由于 R 派系总人数限制为 22,因此小 R 老师战队无法容纳 22 号学校的选手,所以他们只能被迫加入Yazid 老师战队。
  • 综上所述,可能的局面仅有这一种。

对于第 22 组数据:

  • 一个显然的事实是,11 号城市的所有选手都无法加入蓝阵营,这是因为 11 号城市的选手总人数超过了蓝阵营的总人数限制,因此他们被迫全部加入红阵营。
  • 对于 22 号城市选手加入蓝阵营的情况,稍加计算可得出共有 1515 种可能的局面。
  • 对于 22 号城市选手加入红阵营的情况,稍加计算可得出共有 77 种可能的局面。
  • 综上所述,可能的局面数为 15+7=2215 + 7 = 22 种。

数据规模与约定

img

其中,M=max{C0,C1,D0,D1}M = \max\left\{C_0, C_1, D_0, D_1\right\}

对于所有测试点,保证 T5T \leqslant5

对于所有测试点中的每一组数据, 保证 cn1000c \leqslant n \leqslant 1000k30k \leqslant 30M2500M \leqslant 25001simin{M,10}1 \leqslant s_i \leqslant \min\left\{M, 10\right\}

另外,请你注意,数据并不保证所有的 cc 个城市都有参赛学校。

提示

另外还有两组附加样例文件,请在附件中下载。

十二省联考命题组温馨提醒您:

数据千万条,清空第一条。
多测不清空,爆零两行泪。

include<bits/stdc++.h>
#define cl(x,r) memset(x,r,sizeof x)
#define FOR(i,a,b) for(int i=a,i##i=b;i<=i##i;++i)
#define ROF(i,a,b) for(int i=a,i##i=b;i>=i##i;--i)
using namespace std;
const int N=2507,S=307,mod=998244353;
int T,n,c,K,x,y,C0,C1,D0,D1,b[N],s[N],p[N],al,sk;
int f[N],g[N],h[N][S],t[N][S],su[N];
long long ans;
vector<int>v[N];
int get(int*a,int x){return x<0?0:a[x];}
void work(){
	cl(p,-1),cl(f,0),cl(g,0),cl(h,0),cl(su,0),ans=0;
	scanf("%d%d%d%d%d%d",&n,&c,&C0,&C1,&D0,&D1),al=sk=0;
	FOR(i,1,n)scanf("%d%d",b+i,s+i),su[b[i]]+=s[i],al+=s[i];
	FOR(i,1,c)v[i].clear();
	C1=max(al-C1,0),D1=max(al-D1,0),f[0]=g[0]=h[0][0]=1;
	for(scanf("%d",&K);K--;)scanf("%d%d",&x,&y),p[x]=y,v[b[x]].push_back(x),sk+=s[x];
	FOR(i,1,n)if(p[i]==-1)ROF(j,D0,s[i])(f[j]+=f[j-s[i]])%=mod;
	FOR(d,1,c)if(v[d].size()){
		memcpy(t,h,sizeof h);
		for(int g:v[d])ROF(i,C0,0)ROF(j,min(sk,D0),0){
			int X=0,Y=0;
			if(p[g]!=0)(X+=get(h[i],j-s[g]))%=mod;
			if(p[g]!=1)(X+=h[i][j])%=mod;
			if(p[g]!=2)(Y+=get(t[i],j-s[g]))%=mod;
			if(p[g]!=3)(Y+=t[i][j])%=mod;
			h[i][j]=X,t[i][j]=Y;
		}
		ROF(i,C0,0)ROF(j,min(sk,D0),0)h[i][j]=((i<su[d]?0:h[i-su[d]][j])+t[i][j])%mod;
	}
	else if(su[d])ROF(i,C0,su[d])(g[i]+=g[i-su[d]])%=mod;
	FOR(i,1,D0)(f[i]+=f[i-1])%=mod;
	FOR(i,1,C0)(g[i]+=g[i-1])%=mod;
	FOR(i,0,C0)FOR(j,0,min(D0,sk))(ans+=1ll*h[i][j]*(f[D0-j]-get(f,D1-j-1))%mod*(g[C0-i]-get(g,C1-i-1)))%=mod;
}
signed main(){
	for(scanf("%d",&T);T--;)work(),printf("%lld\n",(ans+mod)%mod);
	return 0;
}