題目
【題目描述】
#### 題目背景
一年一度的綜藝節目《中國好碼農》又開始了。本季度,好碼農由 Yazid、Zayid、小 R、大 R 四位夢想導師坐鎮,他們都將組建自己的夢想戰隊,并率領隊員向夢想發起沖擊。
四位導師的**派系**不盡相同,節目組為了營造看點,又將導師分成了不同的**陣營**,與此同時對不同陣營、不同派系都作出了戰隊總人數限制:
- 四位導師分成兩個**陣營**:
- Yazid、小 R 兩位導師組成**藍陣營**,他們兩位的戰隊人數**總和**不得超過 $C_0$。
- Zayid、大 R 兩位導師組成**紅陣營**,他們兩位的戰隊人數**總和**不得超過 $C_1$。
- 四位導師分成兩個**派系**:
- Yazid、Zayid 兩位導師屬于**鴨派系**,他們兩位的戰隊人數**總和**不得超過 $D_0$。
- 小 R、大 R 兩位導師屬于 **R 派系**,他們兩位的戰隊人數**總和**不得超過 $D_1$。
#### 題目描述
本季好碼農邀請到了全國各路學生精英參賽。他們來自全國 $c$ 個城市的 $n$ 所不同學校(城市的編號從 $1$ 至 $c$,學校的編號從 $1$ 至 $n$)。其中,第 $i$ 所學校所屬的城市編號為 $b_i$,且共有 $s_i$ 名選手參賽。
在「題目背景」中提到的各總人數限制之外,本季度《中國好碼農》的導師選擇階段有額外規則如下:
- 來自同**城市**的所有選手必須加入相同的**陣營**。
- 來自同**學校**的所有選手必須選擇相同的**導師**。
對于導師,大部分學校的學生對導師沒有**偏好**。但是有 $k$ 所學校,其中每所學校的學生有且僅有一位他們不喜歡的導師。同一所學校的學生不喜歡的導師相同,他們**不會加入他們不喜歡的導師的戰隊**。
面對琳瑯滿目的規則和選手的偏好,作為好碼農忠實觀眾的你想計算出,在所有選手都進行了戰隊選擇后,戰隊組成共有多少種可能的局面?
- 兩種戰隊組成的局面被認為是不同的,當且僅當在存在一所學校,使得在這兩種局面中這所學校的選手加入了不同導師的戰隊。
- 由于答案可能很大,你只需輸出可能局面數對 $998,244,353$ 取模的結果即可。
【輸入格式】
從標準輸入讀入數據。
單個測試點中包含多組數據,輸入的第一行包含一個非負整數 $T$ 表示數據組數。接下來依次描述每組數據,對于每組數據:
- 第 $1$ 行 $2$ 個正整數 $n,c$,分別表示學校數目、城市數目。
- 第 $2$ 行 $4$ 個正整數 $C_0,C_1,D_0,D_1$,分別表示題目中所描述的四個限制。
- 接下來 $n$ 行每行 $2$ 個正整數:
- 這部分中第 $i$ 行的兩個數依次為 $b_i,s_i$,分別表示第 $i$ 所學校的所屬城市以及選手數目。
- 保證 $b_i \leq c$,$s_i \leq \min\{M, 10\}$。其中 $M=\max{\left\{ C_0,C_1,D_0,D_1\right\}}$。
- 接下來 $1$ 行一個非負整數 $k$,表示選手有偏好的學校數目。
- 接下來 $k$ 行,每行 $2$ 個整數 $i,p$,描述編號為 $i$ 的學校選手有偏好:
- 其中,$p$ 為一個 $0$ 至 $3$ 之間的整數,描述該校選手不喜歡的導師:0 代表 Yazid,1 代表小 R,2 代表 Zayid,3 代表大 R。
- 保證 $1\leq i\leq n$,且各行的 $i$ 互不相同。
對于輸入的每一行,如果其包含多個數,則用單個空格將它們隔開。
【輸出格式】
輸出到標準輸出。
依次輸出每組數據的答案,對于每組數據:
- 一行一個整數,表示可能局面數對 $998,244,353$ 取模的結果。
【樣例輸入】
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
22
【樣例解釋】
對于第 1 組數據:
- 唯一的城市 1 包含共 $3$ 名選手,但紅陣營的總人數限制為 $2$,無法容納這些選手,因此他們被迫只能選擇藍陣營。
- 在此基礎上,由于 1 號學校的選手不喜歡 Yazid 老師,因此他們就必須加入 R 派系的小 R 老師麾下。
- 由于 R 派系總人數限制為 $2$,因此小 R 老師戰隊無法容納 2 號學校的選手,所以他們只能被迫加入 Yazid 老師戰隊。
- 綜上所述,可能的局面僅有這一種。
對于第 2 組數據:
- 一個顯然的事實是,1 號城市的所有選手都無法加入藍陣營,這是因為 1 號城市的選手總人數超過了藍陣營的總人數限制,因此他們被迫全部加入紅陣營。
- 對于 2 號城市選手加入藍陣營的情況,稍加計算可得出共有 $15$ 種可能的局面。
- 對于 2 號城市選手加入紅陣營的情況,稍加計算可得出共有 $7$ 種可能的局面。
- 綜上所述,可能的局面數為 $15+7=22$ 種。
【數據范圍與提示】
|測試點|$n$|$c$|$k$|$M$|
|:-:|:-:|:-:|:-:|:-:|
|$1$|$=1$|$=n$|$\le 1$|$=1$|
|$2$|$=10$|$=n$|$\le 10$|$\le 100$|
|$3$|$=20$|$=n$|$=0$|$\le 100$|
|$4$|$=30$|$=n$|$=0$|$\le 100$|
|$5$|$=30$|$=n$|$\le 30$|$\le 500$|
|$6$|$=500$|$=n$|$=0$|$\le 1000$|
|$7$|$=500$|$=30$|$= 30$|$\le 1000$|
|$8$|$=500$|$=n$|$= 30$|$\le 1000$|
|$9$|$=1000$|$=n$|$=0$|$\le 2500$|
|$10$|$=1000$|$=n$|$=30$|$\le 2500$|
其中,$M=\max{\left\{ C_0,C_1,D_0,D_1\right\}}$。
對于所有測試點,保證 $T\leq 5$。
對于所有測試點中的每一組數據,保證 $c\leq n\leq 1000$,$k\leq 30$,$M\leq 2500$,$1\leq s_i \leq \min\{M, 10\}$。
**另外,請你注意,數據并不保證所有的 $c$ 個城市都有參賽學校。**
#### 提示
十二省聯考命題組溫馨提醒您:
**數據千萬條,清空第一條。**
**多測不清空,爆零兩行淚。**
題解
這是一個 t1 難度 $ > $ t2 的故事
首先,是一個 $ 50 \% $ 的暴力
記 $ f[i][j][k] $ 表示前 $ i $ 個人,有 $ j $ 個在 $ 1 $ 陣營(藍陣營,下同),有 $ k $ 個在 $ 1 $ 派系(鴨派系,下同)的方案數,然后隨便轉移,效率 $ O(nm^2) $
然后發現,如果沒有限制的話,陣營和派系的人數是互不影響的,接著就可以根據這個搞事情
記 $ g1[i][j] $ 表示前 $ i $ 個城市(沒有限制的),有 $ j $ 個在 $ 1 $ 陣營的方案數
$ g1[i][j]=g[i-1][j]+g[i-1][j-A[i]],A[i] $ 表示第 $ i $ 個城市的人數
記 $ g2[i][j] $ 表示前 $ i $ 個學校(沒有限制的),有 $ j $ 個在 $ 1 $ 派系的方案數
$ g1[i][j]=g[i-1][j]+g[i-1][j-B[i]],B[i] $ 表示第 $ i $ 個學校的人數
發現 $ g1, g2 $ 是一個背包,可以壓成一位來搞
記 $ f[j][k] $ 同之前的定義,滾掉第一維,用于轉移有限制的城市和學校
對于城市,不同陣營的老師對派系的影響是不同的,因此記 $ h=f $ 記錄不同派系的轉移
先是對學校的轉移( $ ban[i] $ 為 $ i $ 學校不喜歡的導師)
$ f[j][k]=\left\{ \begin{matrix} f[j][k-B[v],ban[i]!=0 \\f[j][k],ban[i]!=1 \end{matrix} \right\} $
$ g[j][k]=\left\{ \begin{matrix} g[j][k-B[v],ban[i]!=2 \\g[j][k],ban[i]!=3 \end{matrix} \right\} $
對于城市的轉移
$ f[i][j]=f[i-A[l]][j]+g[i][j] $
考慮如何合并答案
枚舉 $ f[i][j] $,則
$ sum-i-c1 \leq x \leq c0-i $,$ x $ 為 $ 1 $ 陣營的人數
$ sum-j-d1 \leq y \leq d0-j $,$ y $ 為 $ 1 $ 派系的人數
則沒有限制的方案數為 $ \sum_{x=sum-i-c1}^{c0-i}\times \sum_{y=sum-j-d1}^{d0-i} $,前綴和優化即可 $ O(1) $ 詢問
時間效率:$ O(km^2) $,時間主要在 $ f $ 上,但是跑不滿
代碼
?代碼寫丑了,常數比較大


1 #include<bits/stdc++.h> 2 #define LL long long 3 #define pb push_back 4 #define clr(s) memset(s,0,sizeof s) 5 #define _(d) while(d(isdigit(ch=getchar()))) 6 using namespace std; 7 int R(){ 8 int x;bool f=1;char ch;_(!)if(ch=='-')f=0;x=ch^48; 9 _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;} 10 const int N=3e3+5,P=998244353; 11 int n,m,K,g1[N],g2[N],f[N][N],h[N][N],c0,c1,d0,d1,ban[N],Ban[N],A[N],B[N],fa[N],sum,ans,s0,s1; 12 vector<int>p[N]; 13 void clean(){ 14 clr(g1),clr(g2),clr(f),clr(h),clr(A),clr(B),clr(fa); 15 for(int i=1;i<=m;i++)p[i].clear(); 16 sum=s0=s1=ans=0; 17 } 18 int make(int x,int y){ 19 int l0=max(0,sum-x-c1),r0=c0-x; 20 int l1=max(0,sum-y-d1),r1=d0-y; 21 if(l0>r0||l1>r1)return 0; 22 return 1ll*(g1[r0]-(l0?g1[l0-1]:0)+P)*(g2[r1]-(l1?g2[l1-1]:0)+P)%P; 23 } 24 int main(){ 25 for(int T=R();T--;clean()){ 26 memset(ban,-1,sizeof ban); 27 memset(Ban,-1,sizeof Ban); 28 n=R(),m=R(),c0=R(),c1=R(),d0=R(),d1=R(); 29 for(int i=1;i<=n;i++){ 30 fa[i]=R(),B[i]=R(); 31 sum+=B[i],A[fa[i]]+=B[i]; 32 p[fa[i]].pb(i); 33 } 34 K=R(); 35 for(int i=1;i<=K;i++){ 36 int id=R(),fl=R(); 37 ban[id]=Ban[fa[id]]=fl; 38 } 39 g1[0]=g2[0]=1; 40 for(int i=1;i<=m;i++) 41 if(!~Ban[i]&&A[i]) 42 for(int j=min(c0,sum);j>=A[i];j--) 43 g1[j]=(g1[j-A[i]]+g1[j])%P; 44 for(int i=1;i<=c0;i++)g1[i]=(g1[i]+g1[i-1])%P; 45 for(int i=1;i<=n;i++) 46 if(!~ban[i]) 47 for(int j=min(d0,sum);j>=B[i];j--) 48 g2[j]=(g2[j-B[i]]+g2[j])%P; 49 for(int i=1;i<=d0;i++)g2[i]=(g2[i]+g2[i-1])%P; 50 f[0][0]=1; 51 for(int i=1;i<=m;i++) 52 if(~Ban[i]&&A[i]){ 53 for(int x=min(c0,s0);~x;x--) 54 for(int y=min(d0,s1);~y;y--) 55 h[x][y]=f[x][y]; 56 for(int v:p[i])if(ban[v]!=-1){ 57 s1+=B[v]; 58 int f00=ban[v]^0?1:0,f01=ban[v]^1?1:0,f10=ban[v]^2?1:0,f11=ban[v]^3?1:0; 59 for(int x=min(c0,s0);~x;x--) 60 for(int y=min(d0,s1);~y;y--) 61 if(y>=B[v]){ 62 f[x][y]=(f[x][y]*f01+f[x][y-B[v]]*f00)%P; 63 h[x][y]=(h[x][y]*f11+h[x][y-B[v]]*f10)%P; 64 } 65 else f[x][y]=f[x][y]*f01,h[x][y]=h[x][y]*f11; 66 } 67 s0+=A[i]; 68 for(int x=min(c0,s0);~x;x--) 69 for(int y=min(c0,s1);~y;y--) 70 if(x>=A[i])f[x][y]=(f[x-A[i]][y]+h[x][y])%P; 71 else f[x][y]=h[x][y]; 72 } 73 for(int i=0;i<=min(s0,c0);i++) 74 for(int j=0;j<=min(s1,d0);j++) 75 ans=(ans+1ll*f[i][j]*make(i,j))%P; 76 cout<<ans<<endl; 77 } 78 return 0; 79 }
?