T763598 座位优化 (seats) 赛后题解
题目传送门
思路
首先考虑把飞机两侧的座椅(靠窗的)合并,使其成为一个中间的座椅,左右都有过道。
考虑任意两组座椅,如果它们的的大小之差大于 \(2\),则显然使它们更平均更优。
做法
对于第一问,考虑让所有的组都平均,及最大与最小的差不超过 \(1\)。此时一定最优。
计算出最小值以及最大值,算出组内的总和,算出两种的数量即可求出答案。
对于第二问,分类讨论。
- 如果 \(k=1\),则不存在中间的座位,答案为
(l & 1) ? 2 : 1。 - 如果 \(l\) 为奇数,则考虑枚举,每次将两个 \(l\) 换为 \(l+1\) 与 \(l-1\),显然不便利度不变。此时总共有 \(3\) 种不同大小的组,组合数计算即可。需要注意,\(l=1\) 时需要特殊处理。
- 如果 \(r\) 为奇数,做法同上。
- 否则答案为 \(1\)。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
int fp(int a, int b)
{
if(b == 0) return 1;
int t = fp(a, b >> 1);
t = t * t % mod;
if(b & 1) return t * a % mod;
return t;
}
int fac[200005], ifac[200005];
int C(int n, int m) {return fac[n] * ifac[m] % mod * ifac[n - m] % mod;}
int sum(int l, int r) {return (l + r) * (r - l + 1) / 2;}
int calc(int x) {return (sum(0, (x - 1) / 2) * 2 - ((x & 1) ? x / 2 : 0));}
int calc2(int s1, int s2, int s3)
{
int n = s1 + s2 + s3;
return C(n, s1) * C(n - s1, s2) % mod;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
freopen("seats.in", "r", stdin);
freopen("seats.out", "w", stdout);
fac[0] = ifac[0] = 1;
for(int i = 1; i <= 200000; i ++)
{
fac[i] = fac[i - 1] * i % mod;
ifac[i] = fp(fac[i], mod - 2);
}
int _;
cin >> _;
while(_ --)
{
int n, k;
cin >> n >> k;
int m = k + 1, l = n / k, r = l + ((n / k * k == n) ? 0 : 1);
cout << (calc(l) * (k - (n % k)) + calc(r) * (n % k)) << ' ';
if(k == 1) cout << ((l & 1) ? 2 : 1) << endl;
else
{
if(l & 1)
{
if(l == 1)
{
int t = calc2(k - (n % k), n % k - 1, 0);
cout << t << endl;
}
else
{
int ans = 0;
for(int i = 0; i <= k - (n % k); i += 2)
{
int t = calc2(i / 2, i / 2 + (n % k), k - (n % k) - i);
ans = (ans + t) % mod;
if(k - (n % k) - i - 1 >= 0)
{
t = calc2(i / 2, i / 2 + (n % k), k - (n % k) - i - 1);
ans = (ans + t) % mod;
}
}
cout << ans << endl;
}
}
else if(r & 1)
{
int ans = 0;
for(int i = 0; i <= n % k; i += 2)
{
int t = calc2(i / 2, i / 2 + k - (n % k), (n % k) - i);
ans = (ans + t) % mod;
if((n % k) - i - 1 >= 0)
{
t = calc2(i / 2, i / 2 + k - (n % k), (n % k) - i - 1);
ans = (ans + t) % mod;
}
}
cout << ans << endl;
}
else cout << 1 << endl;
}
}
return 0;
}
hello, I'm yuzihang, if you need to copy this, please quote this url: https://www.cnblogs.com/yuzihang/p/20133474

浙公网安备 33010602011771号