JZOJ 5923. 【NOIP2018模拟10.23】Bomb
Description
常數國與 Hack 國近年來戰火紛飛。
常數國共有 n 個城市,每兩個城市之間均有一條交通線聯通。如今常數國遭到 Hack 國的重創,岌岌可危。Hack 國國王小 K 決定轟炸常數國的交通線,對常數國發起最后的攻擊。
面對危難之時,常數國國王決定更換首都。在 Hack 國的轟炸結束之后,常數國的領土將會分成若干個聯通塊。常數國的首都,將會從聯通塊大小最大的聯通塊中,隨機選擇一個城市,作為首都。
小 K 得知了常數國的應對方案之后,他想知道,Hack 國有多少種不同的轟炸方案,使得常數首都所在的聯通塊大小恰好為 k。兩種轟炸方案是不同的,當且僅當一條交通線在一種方案中存在,在另一種方案中被轟炸。由于方案數可能很大,你需要輸出方案數對 998,244,353 取模的結果。
Input
從文件bomb.in中讀入數據。
共一行,兩個整數 n,k ,表示常數國城市的個數與首都所在聯通塊大小。
Output
輸出到文件bomb.out中。
共一行,表示 Hack 國的轟炸方案數對 998,244,353 取模后的結果。
Sample Input
?Sample Input 1
3 2
Sample Input 2
5 3
Sample 3
見選手目錄下的bomb/bomb3.in與bomb/bomb3.ans。
該組樣例的數據范圍同第 8 個測試點。
Sample Output
Sample Output1
3
Explanation
3 種方案分別為,僅保留 1 號城市與 2 號城市的交通線,僅保留 2 號城市與3 號城市的交通線,僅保留 1 號城市與 3 號城市的交通線。
Sample Output2
80
Data Constraint
對于 100% 的數據,滿足 1 ≤ k ≤ n ≤ 2 × 10 3 。除此之外,對于每個數據點,還滿足以下限制。
Solution
-
我們需要靈活地DP!
-
考慮設 f[i]f[i]f[i] 表示大小為 iii 的連通圖的個數。
-
為了求出 f[i]f[i]f[i] ,我們再設一個 h[i]h[i]h[i] 表示大小為 iii 的圖的個數。
-
則有:h[0]=1,h[i]=h[i?1]?2i?1h[0]=1,h[i]=h[i-1]*2^{i-1}h[0]=1,h[i]=h[i?1]?2i?1
-
即:h[i]=2Ci2h[i]=2^{C_{i}^{2}}h[i]=2Ci2?
-
那么 f[i]f[i]f[i] 就很好求了:f[i]=h[i]?∑j=1i?1Ci?1j?1?f[j]?h[i?j]f[i]=h[i]-\sum_{j=1}^{i-1}C_{i-1}^{j-1}*f[j]*h[i-j]f[i]=h[i]?j=1∑i?1?Ci?1j?1??f[j]?h[i?j]
-
注意這些點是有編號的,所以組合數應為 Ci?1j?1C_{i-1}^{j-1}Ci?1j?1? 而非 CijC_{i}^{j}Cij? 。
-
求出了 f[i]f[i]f[i] 我們就更容易求出答案了。
-
設 g[i]g[i]g[i] 為大小為 iii 的圖的個數,其中這些圖中的連通塊大小不超過 kkk。
-
于是就有轉移:g[i]=∑j=1min(i,k)Ci?1j?1?f[j]?g[i?j]g[i]=\sum_{j=1}^{min(i,k)}C_{i-1}^{j-1}*f[j]*g[i-j]g[i]=j=1∑min(i,k)?Ci?1j?1??f[j]?g[i?j]
-
由于 ggg 表示的圖的連通塊大小 ≤k\leq k≤k ,那么我們又設一個 g1[i]g1[i]g1[i] 表示 ≤k?1\leq k-1≤k?1 的。
-
轉移即把上面的 kkk 換成 k?1k-1k?1。
-
那么答案就是 g[n]?g1[n]g[n]-g1[n]g[n]?g1[n] 。
-
時間復雜度 O(n2)O(n^2)O(n2) ,用FFT優化可達 O(nlogn)O(n\ log\ n)O(n?log?n) 。
-
這題的DP方式比較套路,但是如果之前沒接觸過的話就不是特別好想,需要多積累。
Code
#include<cstdio> #include<cctype> using namespace std; typedef long long LL; const int N=2005,mo=998244353; int f[N],g[N],g1[N],h[N],c[N][N]; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline int ksm(int x,int y) {int s=1;while(y){if(y&1) s=(LL)s*x%mo;x=(LL)x*x%mo;y>>=1;}return s; } int main() {freopen("bomb.in","r",stdin);freopen("bomb.out","w",stdout);int n=read(),k=read();for(int i=0;i<=n;i++) c[i][0]=1;for(int i=1;i<=n;i++)for(int j=1;j<=i;j++)c[i][j]=(c[i-1][j-1]+c[i-1][j])%mo;f[0]=g[0]=g1[0]=h[0]=1;for(int i=1;i<=n;i++){h[i]=ksm(2,i*(i-1)/2);for(int j=1;j<i;j++)f[i]=(f[i]+(LL)c[i-1][j-1]*f[j]%mo*h[i-j])%mo;f[i]=(mo-f[i]+h[i])%mo;for(int j=1,up=i<k?i:k;j<=up;j++) g[i]=(g[i]+(LL)c[i-1][j-1]*f[j]%mo*g[i-j])%mo;for(int j=1,up=i<k-1?i:k-1;j<=up;j++) g1[i]=(g1[i]+(LL)c[i-1][j-1]*f[j]%mo*g1[i-j])%mo;}printf("%d",(g[n]-g1[n]+mo)%mo);return 0; }總結
以上是生活随笔為你收集整理的JZOJ 5923. 【NOIP2018模拟10.23】Bomb的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 5905. 【NOIP2018
- 下一篇: JZOJ 5922. 【NOIP2018