ABC297F Minimum Bounding Box 2 题解
题意简述
定义
解题思路
我们发现若要找出
但可以发现这也并不是特别好求。不妨思考:如何把抽象的、不确定位置的矩形,转化成确切的、已知的信息?我们发现:
也就是说,我们只需要做到求单个方格被覆盖的次数,就可以求解全局的答案。
但是令人不爽的是,就算具体到如此程度,也不是很好求。考虑正难则反,求所有情况下不覆盖方格
中的至少一条。
但是我们发现可能会重复统计完全在左上、左下、右上、右下的情况。容斥一下就可以了。具体实现可以见下面的代码。
代码实现
#include<cstdio>
#include<iostream>
#include<vector>
//此处省略 10000 字快读。
#define int long long
#define R myio::read_int()
//也就是说,后面的 R 表示读入一个整数。
const int S=1e6,P=998244353;
int fac[S+6],inv[S+6];
int Qpow(int x,int y) {
int ret=1;
for(;y>0;y>>=1) {
if(y&1) (ret*=x)%=P;
(x*=x)%=P;
} return ret;
}
void pret() { //预处理阶乘与阶乘逆元。
fac[0]=1;
for(int i=1;i<=S;i++) fac[i]=fac[i-1]*i%P;
inv[S]=Qpow(fac[S],P-2);
for(int i=S-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%P;
}
int C(int n,int m) {
if(n<m) return 0;
return fac[n]*inv[m]%P*inv[n-m]%P;
}
signed main() {
pret();
int h=R,w=R,k=R,cnt=C(h*w,k);
int invcnt=Qpow(cnt,P-2);
cnt=cnt*h%P*w%P; //这里就是计算的“选方格的情况总数”。
for(int i=1;i<=h;i++) for(int j=1;j<=w;j++) {
int lx=C((i-1)*w,k),ux=C((h-i)*w,k);
int ly=C((j-1)*h,k),uy=C((w-j)*h,k);
//计算上文提到条件满足的矩形的个数。
//l 指的是 "lower",较小的;r 指的是 'upper',较大的。
int lxly=C((i-1)*(j-1),k),uxuy=C((h-i)*(w-j),k);
int lxuy=C((i-1)*(w-j),k),uxly=C((h-i)*(j-1),k);
//容斥,去掉重复的部分。
(cnt-=(lx+ly+ux+uy-lxly-uxuy-lxuy-uxly))%=P;
}
myio::print_int(((cnt*invcnt)%P+P)%P);
//因为取模有可能是负数,因此要转化成自然数。
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律