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);
}
}
本文来自博客园,作者:ricky_lin,转载请注明原文链接:https://www.cnblogs.com/rickylin/p/19021162/ARC203

浙公网安备 33010602011771号