CF1931G One-Dimensional Puzzle 题解
CF1931G One-Dimensional Puzzle 题解
题意传送门
思路
考虑一下怎么入手,发现一个拼图只能接一些拼图(废话但是有用),所以我们可以简单地画出一个链接关系的图, 表示编号为 的拼图后面能够接编号为 的拼图。然后我们发现问题转换为:在这张图上找到一个正好经过每个节点特定次数的路径。
仔细观察这张图,我们可以发现, 号拼图一定是轮流出现的,也就是说 号拼图的数量差一定不能大于 ,不然的话一定会剩下一些 号或者 号拼图。之后可以发现 号只能接在 中间, 号只能接在 中间。
之后分类讨论:
- 如果 的数量和 的数量的差大于 ,则直接输出 。
- 如果 的数量都为 但是 的数量中只有一个或者都为 ,那么就有一种方案。
- 如果 的数量和 的数量相同,就有两种 的排列情况。(假设 的数量都有 个)
第一种, 先出现:,这样能放 的区间有 个,能放 的区间有 个。
第一种, 先出现:,这样能放 的区间有 个,能放 的区间有 个。 - 如果 的数量和 的数量相差 ,就只有一种排列情况。(假设 的数量中较小的一个数量为 个)
可能是 或者 ,这样能放 的区间个数和能放 的区间个数都是 了。
最后我们考虑一个组合数学的问题,就是我们有 个抽屉和 颗球,将球全部放入抽屉中,抽屉可以空着,有多少种放的方法(对应上文放 号拼图的情况)。
首先,放入 个抽屉其实就是将原本的 个球分成 个部分,在 个球中插入 个隔板,有 个可以插板的地方。因为抽屉可以是空着的,所以隔板可以放在一起,为了方便考虑,所以我们可以增加 个球,这样就等于每个抽屉都多一个球,就是原本空抽屉的情况就变成了一个球的情况,最后原问题的答案就是将 个板子插入 个空的方案数,也就是 ,需要用快速幂和逆元维护组合数,具体来说,逆元就是一个性质:在 的意义下( 为质数)时,。
喜闻乐见代码环节
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define int long long
const int mod=998244353;
int t1,t2,t3,t4;
int quick_power(int x,int y){
int ret=1,base=x;
while(y){
if(y&1) ret=ret*base%mod;
base=base*base%mod;
y>>=1;
}
return ret;
}
int C(int n,int m){
int ret=1;
for(int i=1;i<=m;i++){
ret=ret*(n+1-i)%mod;
ret=ret*quick_power(i,mod-2)%mod;
}
return ret;
}
signed main(){
int t;
scanf("%lld",&t);
while(t--){
scanf("%lld%lld%lld%lld",&t1,&t2,&t3,&t4);
if(t1+t2==0&&t3*t4==0){
printf("1\n");
continue;
}
if(abs(t1-t2)>1||t1+t2==0){
printf("0\n");
continue;
}
if(t1!=t2){
int m=min(t1,t2);
printf("%lld\n",C(t3+m,m)*C(t4+m,m)%mod);
}
if(t1==t2)
printf("%lld\n",(C(t3+t1,t1)*C(t4+t1-1,t1-1)%mod+C(t3+t1-1,t1-1)*C(t4+t1,t1)%mod)%mod);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】