ARC203 题解

A. All Winners

tag:思维题

如果说每个队有 \(1\) 个人,那么很简单,答案就是 \(1\),方案也很好构造,一个人全赢,其他人便不可能再全赢

如果说每个队有 \(2\) 个人,那么很简单,答案就是队伍个数,方案也很好构造,一个队中一个人全赢,一个人全输

我们按照上面进行扩展:

  • 如果有 \(2\times i\) 个人,那么答案就是 \(i\times n\)

  • 如果有 \(2\times i + 1\) 个人,那么答案就是 \(i\times n + 1\)

code
#include<bits/stdc++.h>
using namespace std;
int T;
int n,m;
int main(){
	ios::sync_with_stdio(false),cin.tie(0); 
	cin >> T;
	while(T--){
		cin >> n >> m;
		if(m & 1){
			cout << 1ll * n * (m/2) + 1 << '\n';
		}
		else{
			cout << 1ll * n * (m/2) << '\n';
		}
	}
} 

B. Swap If Equal Sum

tag: 思维题

首先,如果说序列中 \(1\) 的个数不同,显然是无法通过操作变成同一个序列的

接着,我们可以发现,如果说 \(1\) 的个数大于等于 \(2\),那么一定可以通过一些操作,将这个序列变成 \(0\dots 01\dots 1\) 的形式

我们只需要考虑只有一个 \(1\) 怎么做?

一开始认为只要 \(1\) 的位置不同就不行,但是发现一堆 \(0\) 之间也可以相互交换,所以只有 \(1\) 在两端的时候序列不能变化,其他均可互相转变

code
#include<bits/stdc++.h>
using namespace std;
const int NN = 2e5 + 8;
int T,n;
int a[NN],b[NN],cnta,cntb,lsta,lstb;
int main(){
	ios::sync_with_stdio(false),cin.tie(0);
	cin >> T;
	while(T--){
		cin >> n;
		cnta = 0;cntb = 0;lsta = 0;lstb = 0;
		for(int i = 1; i <= n; ++i){
			cin >> a[i];
			if(a[i]) ++cnta,lsta = i;
		}
		for(int i = 1; i <= n; ++i){
			cin >> b[i];
			if(b[i]) ++cntb,lstb = i;
		}
		if(cnta != cntb){
			puts("No");
		}
		else if(cnta == 1){
			if(lsta == lstb){
				puts("Yes");continue;
			}
			
			if(lsta == 1 || lsta == n || lstb == 1 || lstb == n){
				puts("No");
			}
			puts("Yes");
		}
		else puts("Yes");
	}
}

C. Destruction of Walls

tag: 数学 计数

如果说 \(K < H+W-2\),显然不可能存在方案,输出 \(0\)

如果说 \(K == H+W-2\),那么显然方案数就是路径数 \(\binom{H+W-2}{H-1}\)

如果说 \(K == H+W-1\),我们可以发现,无论打破哪一面墙都不会影响到最后的路径,所以方案数为 \(\binom{H+W-2}{H-1}\times (n\times (m-1) + m\times (n-1) - n - m + 2)\)

我们现在记 \(rese = n\times (m-1) + m\times (n-1) - n - m + 2\)

那么,首先对于长度为 \(H+W-2\) 的路径,我们重复计数的情况只可能是有回路的情况,大概是 RDLU 这个样子

那怎么去重呢,我们探究发现,我们相当于是走从 \((1,1)\sim (H-1,W-1)\),然后将中间某一格子变成 \(2\times 2\) 即可,答案是 \(binom(H + W - 4, H - 2) \times (H+W-3)\)

长度为 \(H+W\) 的路径计数,这种路径会出现一次向上或向左的操作。

若向上走,那么我们上一次必须是向右,并且下一次也必须是向右。

于是我们将这三个操作(RUR) 合并成一个操作(U),求出合并后的序列的种类,再乘以 \(U\) 的个数,那么就可以求出方案数 \(\binom{H + W - 2}{W - 3})\times (H-1)\)

向左走同理

code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 998244353;
const int NN = 4e5 + 8, N = 4e5;
int T;
int H,W,K;
ll frac[NN],inv[NN];
ll ksm(ll x,ll k){
	ll ans = 1;
	x %= MOD;
	while(k){
		if(k&1) ans = ans * x % MOD;
		x = x * x % MOD;
		k >>= 1;
	}
	return ans;
}
void init(){
	frac[0] = 1;
	for(int i = 1; i <= N; ++i){
		frac[i] = frac[i-1] * i % MOD;
	}
	inv[N] = ksm(frac[N],MOD - 2);
	for(int i = N; i >= 1; --i){
		inv[i-1] = inv[i] * i % MOD;
	}
}
inline ll binom(int n,int m){
	return frac[n] * inv[m] % MOD * inv[n-m] % MOD;
}
int main(){
	init();
	cin >> T;
	while(T--){
		cin >> H >> W >> K;
		ll num1 = binom(H+W-2,H-1), num2 = 2ll * (1ll * H * W - H - W + 1);
		num2 %= MOD;
		if(K < H + W - 2) cout << "0\n";
		else if(K == H + W - 2) cout << num1 << '\n';
		else if(K == H + W - 1) cout << num1 * num2 % MOD << '\n';
		else if(K == H + W){
			ll num3 = num2 * (num2 - 1) % MOD * inv[2] % MOD;
			ll num4 = binom(H + W - 4, H - 2) * (H+W-3) % MOD;
			ll ans = (num1 * num3 - num4) % MOD;
			if(H >= 3) ans = (ans + binom(H + W - 2, H - 3)*(W-1) % MOD) % MOD;
			if(W >= 3) ans = (ans + binom(H + W - 2, W - 3)*(H-1) % MOD) % MOD;
			
			cout << ans << '\n';
		}
		else assert(1);
	}
}
posted @ 2025-08-04 11:15  ricky_lin  阅读(55)  评论(0)    收藏  举报