【AGC002F】 Leftmost Ball 题解 (朴素 dp)
朴素 dp
Solution
题面看起来很难——不同的两种排序方案,可能染色之后对应的是同种状态。
那就不妨反向考虑——从最终状态,倒退它能指向多少种初始状态。
根据题意,一种颜色对应着一个白球,这引导着我们从每种颜色的角度考虑,即每次考虑把当前颜色都放进去。
然后你就能根据强大的经验设计出 dp 的策略:从左往右放,每次对最左边的一个空位,要么放一个白球,要么放一个有颜色的球,同时把该种颜色剩下的球都放到后面的位置去。
即,定义
根据策略:要么放一个白球,要么放一种颜色,转移就很显然了。
注意答案最后要乘上
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(register int i = a; i <= b; ++i)
#define per(i, a, b) for(register int i = a; i >= b; --i)
const int maxn = 2005, mod = 1e9 + 7;
int f[maxn][maxn], n, k;
int fac[maxn * maxn], inv[maxn * maxn];
inline int pow(int x, int p){ int res = 1;
while(p){ if(p & 1) res = res * x % mod;
p /= 2, x = x * x % mod;
} return res;
}
inline int C(int t, int m){
if(t < m or t < 0 or m < 0) return 0;
return fac[t] * inv[m] % mod * inv[t - m] % mod;
}
signed main(){ scanf("%lld%lld", &n, &k);
if(k == 1) return printf("1"), 0;
fac[0] = 1; rep(i, 1, n * k) fac[i] = fac[i - 1] * i % mod;
inv[n * k] = pow(fac[n * k], mod - 2);
per(i, n * k - 1, 1) inv[i] = inv[i + 1] * (i + 1) % mod;
f[0][0] = 1, inv[0] = 1;
rep(i, 1, n) rep(j, 0, i){
if(j <= i - 1) f[i][j] = (f[i][j] + f[i - 1][j]) % mod;
if(j) f[i][j] = (f[i][j] + C(n * k - (j - 1) * (k - 1) - i - 1, k - 2) * f[i][j - 1] % mod) % mod;
} return printf("%lld", fac[n] * f[n][n] % mod), 0;
}
感谢阅读。
标签:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通