The 2021 CCPC Weihai Onsite - M. 810975 题解
题意
Zayin进行了
思路
问题转化
考虑败场分割胜场(这是一个经典解法:隔板法),问题转化为
的非负整数解个数(整数拆分问题)。
TIP: 如果你打算跑NTT快速幂 / 生成函数展开,看到这里就结束了。
引理
的非负整数解个数为
引理证明
先考虑正整数解个数
考虑有
O _ O _ O _ O _ O _ ....... _ O _ O // O 表示球, _ 表示空位
那么往空位塞入
再考虑非负整数解个数
令
也就是考虑:先给每组球多塞一个球,作上述隔板法,就可以扩展到非负整数了
即
因为第三个式子正整数解个数即为
至此,我们得到了
回到原问题
以和引理一样的思路,我们考虑某一场比赛 至少 赢了
为了防止问题太过抽象,我们考虑
首先,我们先抽一个
同理,
通过式子所代表的含义,我们列举出生成的
发现不对,y[1] >= 3 or y[2] >= 3
(记作 y[1] >= 3 + y[2] >= 3
(记作 y[1] >= 3 and y[2] >= 3
(记作
最后
小细节
具体看代码特判
代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const i64 MOD = 998244353;
const int N = 1e5 + 6;
i64 fac[N], inv[N], ifac[N];
void norm(i64 &x) {
while(x>=MOD) x -= MOD;
while(x<0) x += MOD;
}
i64 C(i64 n,i64 m) {
if(m<0 || n<m) return 0;
return fac[n] * ifac[m] % MOD * ifac[n-m] % MOD;
}
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
// freopen("in.txt","r",stdin);
fac[0] = fac[1] = 1;
inv[0] = inv[1] = 1;
ifac[0] = ifac[1] = 1;
for(int i=2;i<N;++i) {
fac[i] = fac[i-1] * i % MOD;
inv[i] = inv[MOD%i] * (MOD-MOD/i) % MOD;
ifac[i] = ifac[i-1] * inv[i] % MOD;
}
i64 n,m,k;
cin >> n >> m >> k;
if(!(n>=m && m>=k)) {
cout << 0;
return 0;
}
if(k==0) {
if(m==0) cout << 1;
else cout << 0;
return 0;
}
vector<i64> a(m+2), b(m+2);
i64 w = m, f = n - m;
i64 ans = 0;
for(int i=1;i*k<=m;++i) {
// k
a[i] = C(f + 1, i) * C(m - i * k + f, f) % MOD;
// k + 1
b[i] = C(f + 1, i) * C(m - i * (k + 1) + f, f) % MOD;
ans += (i&1) ? (a[i] - b[i]) : (b[i] - a[i]);
norm(ans);
}
cout << ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!