Description
常数国与 Hack 国近年来战火纷飞。
常数国共有 n 个城市,每两个城市之间均有一条交通线联通。如今常数国遭到 Hack 国的重创,岌岌可危。Hack 国国王小 K 决定轰炸常数国的交通线,对常数国发起最后的攻击。
面对危难之时,常数国国王决定更换首都。在 Hack 国的轰炸结束之后,常数国的领土将会分成若干个联通块。常数国的首都,将会从联通块大小最大的联通块中,随机选择一个城市,作为首都。
小 K 得知了常数国的应对方案之后,他想知道,Hack 国有多少种不同的轰炸方案,使得常数首都所在的联通块大小恰好为 k。两种轰炸方案是不同的,当且仅当一条交通线在一种方案中存在,在另一种方案中被轰炸。由于方案数可能很大,你需要输出方案数对 998,244,353 取模的结果。
常数国共有 n 个城市,每两个城市之间均有一条交通线联通。如今常数国遭到 Hack 国的重创,岌岌可危。Hack 国国王小 K 决定轰炸常数国的交通线,对常数国发起最后的攻击。
面对危难之时,常数国国王决定更换首都。在 Hack 国的轰炸结束之后,常数国的领土将会分成若干个联通块。常数国的首都,将会从联通块大小最大的联通块中,随机选择一个城市,作为首都。
小 K 得知了常数国的应对方案之后,他想知道,Hack 国有多少种不同的轰炸方案,使得常数首都所在的联通块大小恰好为 k。两种轰炸方案是不同的,当且仅当一条交通线在一种方案中存在,在另一种方案中被轰炸。由于方案数可能很大,你需要输出方案数对 998,244,353 取模的结果。
Input
从文件bomb.in中读入数据。
共一行,两个整数 n,k ,表示常数国城市的个数与首都所在联通块大小。
共一行,两个整数 n,k ,表示常数国城市的个数与首都所在联通块大小。
Output
输出到文件bomb.out中。
共一行,表示 Hack 国的轰炸方案数对 998,244,353 取模后的结果。
共一行,表示 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 。除此之外,对于每个数据点,还满足以下限制。
题解
- 考虑一下dp
- 设f[i]为大小为i的联通块的个数,h[i]为大小为i的图的个数
- 其实转移状态很显然
- 可以设dp[i][j]为大小为i的图的个数,j=1有联通块等于k,j=0所有联通块小于k
- 状态转移方程为
代码
1 #include <cstdio> 2 #include <iostream> 3 #define N 2010 4 #define mo 998244353 5 using namespace std; 6 int n,k; 7 long long mi[N*N],f[N][2],F[N],g[N],c[N][N]; 8 int main() 9 { 10 scanf("%d%d",&n,&k); 11 mi[0]=1; for (int i=1;i<=n*n;i++) mi[i]=mi[i-1]*2%mo; 12 c[0][0]=1; 13 for (int i=1;i<=n;i++) 14 { 15 c[i][0]=1; 16 for (int j=1;j<=i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mo; 17 } 18 F[1]=0,g[1]=1; 19 for (int i=2;i<=n;i++) 20 { 21 for (int j=1;j<=i-1;j++) F[i]=(F[i]+g[j]*(g[i-j]+F[i-j])%mo*c[i-1][j-1]%mo)%mo; 22 g[i]=(mi[i*(i-1)/2]-F[i]+mo)%mo; 23 } 24 memset(f,0,sizeof(f)),f[0][0]=1; 25 for (int i=1;i<=n;i++) 26 for (int j=1;j<=k;j++) 27 if (i-j>=0) 28 for (int z=0;z<=1;z++) 29 f[i][z|(j==k)]=(f[i][z|(j==k)]+f[i-j][z]*g[j]%mo*c[i-1][j-1]%mo)%mo; 30 printf("%lld",f[n][1]); 31 }