2023冲刺国赛模拟 36.1
最近越来越懒了,估了很长时间的题解, OI 生涯结束前是凑不够 200 篇博客了,但退役前还是努力写点东西吧。
第一次写题解的大约在暑假集训,原因是当时改模拟赛题目经常参考学长的博客,于是自己也尝试这写了博客;然而省选以后,改题就很少参考学长的博客,一个原因是很难找到模拟赛题目的题解,一个原因是下发题解大多数也能理解了(貌似不理解的题都被我直接弃了)。从那之后自己的题解就变的很不连续, 3 个多月只写了 40 篇左右题解。
T1 染色题
观察题目的性质,容易发现奇数位置和偶数位置的颜色互不干扰,对于任意序列,如果
code
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int max1 = 1e6;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
int n, m, Min[max1 + 5];
int f[max1 + 5], sum[max1 + 5], ans;
void Add ( int &x, int y )
{
x += y;
if ( x >= mod )
x -= mod;
return;
}
int main ()
{
freopen("colour.in", "r", stdin);
freopen("colour.out", "w", stdout);
scanf("%d%d", &n, &m);
for ( int i = 1; i <= n; i ++ )
Min[i] = i;
for ( int i = 1, L, R; i <= m; i ++ )
{
scanf("%d%d", &L, &R);
if ( R > 2 )
Min[R - 2] = min(Min[R - 2], L);
}
for ( int i = n - 1; i >= 1; i -- )
Min[i] = min(Min[i + 1], Min[i]);
f[0] = sum[0] = ans = 1;
for ( int i = 1; i <= n - 2; i ++ )
{
if ( i > 1 )
f[i] = sum[i - 2];
int p = Min[i] - 1 - ((Min[i] ^ i) & 1);
if ( p >= 0 )
Add(f[i], sum[p]);
sum[i] = f[i];
if ( i > 1 )
Add(sum[i], sum[i - 2]);
Add(ans, f[i]);
}
ans = 8LL * ans % mod;
printf("%d\n", ans);
return 0;
}
T2 石头剪刀布
首先考虑枚举
设函数
code
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <ctime>
#include <iostream>
using namespace std;
const int max1 = 3e5;
const int mod = 998244353;
int n, m;
char s[max1 + 5];
int inv[max1 + 5];
struct Data
{
int f[3];
void Clear ()
{
memset(f, 0, sizeof(f));
return;
}
Data operator + ( const Data &A ) const
{
Data res; res.Clear();
res.f[0] = (res.f[0] + 1LL * f[0] * A.f[0]) % mod;
res.f[0] = (res.f[0] + 2LL * f[0] * A.f[1] % mod * inv[3]) % mod;
res.f[1] = (res.f[1] + 1LL * f[0] * A.f[1] % mod * inv[3]) % mod;
res.f[0] = (res.f[0] + 1LL * f[0] * A.f[2] % mod * inv[3]) % mod;
res.f[2] = (res.f[2] + 2LL * f[0] * A.f[2] % mod * inv[3]) % mod;
res.f[1] = (res.f[1] + 1LL * f[1] * A.f[1]) % mod;
res.f[1] = (res.f[1] + 2LL * f[1] * A.f[2] % mod * inv[3]) % mod;
res.f[2] = (res.f[2] + 1LL * f[1] * A.f[2] % mod * inv[3]) % mod;
res.f[1] = (res.f[1] + 1LL * f[1] * A.f[0] % mod * inv[3]) % mod;
res.f[0] = (res.f[0] + 2LL * f[1] * A.f[0] % mod * inv[3]) % mod;
res.f[2] = (res.f[2] + 1LL * f[2] * A.f[2]) % mod;
res.f[2] = (res.f[2] + 2LL * f[2] * A.f[0] % mod * inv[3]) % mod;
res.f[0] = (res.f[0] + 1LL * f[2] * A.f[0] % mod * inv[3]) % mod;
res.f[2] = (res.f[2] + 1LL * f[2] * A.f[1] % mod * inv[3]) % mod;
res.f[1] = (res.f[1] + 2LL * f[2] * A.f[1] % mod * inv[3]) % mod;
return res;
}
};
Data P[max1 + 5][20];
pair <Data, int> Q[max1 + 5][20];
pair <Data, int> Solve ( int L, int R, int x, int y )
{
pair <Data, int> res;
if ( L >= x && R <= y )
return Q[L][__lg(R - L + 2)];
int mid = (L + R) >> 1;
if ( y <= mid )
{
res = Solve(L, mid - 1, x, y);
res.first = res.first + P[mid][__lg(R - mid + 1)];
return res;
}
if ( x >= mid )
{
res = Solve(mid + 1, R, x, y);
res.first = P[L][__lg(mid - L + 1)] + res.first;
return res;
}
pair <Data, int> resL = Solve(L, mid - 1, x, y), resR = Solve(mid + 1, R, x, y);
resL.first = resL.first + P[mid][__lg(R - mid + 1)];
resR.first = P[L][__lg(mid - L + 1)] + resR.first;
res.second = resL.second + resR.second;
res.first.f[0] = (1LL * resL.first.f[0] * resL.second + 1LL * resR.first.f[0] * resR.second) % mod * inv[res.second] % mod;
res.first.f[1] = (1LL * resL.first.f[1] * resL.second + 1LL * resR.first.f[1] * resR.second) % mod * inv[res.second] % mod;
res.first.f[2] = (1LL * resL.first.f[2] * resL.second + 1LL * resR.first.f[2] * resR.second) % mod * inv[res.second] % mod;
return res;
}
int main ()
{
freopen("rps.in", "r", stdin);
freopen("rps.out", "w", stdout);
scanf("%d%d%s", &n, &m, s + 1);
inv[1] = 1;
for ( int i = 2; i <= max(3, n); i ++ )
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
for ( int i = 1; i <= n; i ++ )
{
P[i][0].Clear();
if ( s[i] == 'R' )
P[i][0].f[0] = 1;
else if ( s[i] == 'S' )
P[i][0].f[1] = 1;
else
P[i][0].f[2] = 1;
}
for ( int k = 1; (1 << k) <= n; k ++ )
for ( int i = 1; i + (1 << k) - 1 <= n; i ++ )
P[i][k] = P[i][k - 1] + P[i + (1 << (k - 1))][k - 1];
for ( int i = 1; i <= n; i ++ )
{
Q[i][1].first.Clear();
Q[i][1].second = 1;
if ( s[i] == 'R' )
Q[i][1].first.f[0] = 1;
else if ( s[i] == 'S' )
Q[i][1].first.f[1] = 1;
else
Q[i][1].first.f[2] = 1;
}
Data tmp1, tmp2;
for ( int k = 2; (1 << k) - 1 <= n; k ++ )
{
for ( int i = 1; i + (1 << k) - 2 <= n; i ++ )
{
Q[i][k].second = Q[i][k - 1].second + Q[i + (1 << (k - 1))][k - 1].second;
tmp1 = Q[i][k - 1].first + P[i + (1 << (k - 1)) - 1][k - 1];
tmp2 = P[i][k - 1] + Q[i + (1 << (k - 1))][k - 1].first;
for ( int j = 0; j < 3; j ++ )
Q[i][k].first.f[j] = 1LL * (tmp1.f[j] + tmp2.f[j]) * inv[2] % mod;
}
}
int L, R, x, y;
while ( m -- )
{
scanf("%d%d%d%d", &L, &R, &x, &y);
printf("%d\n", Solve(L, R, x, y).first.f[0]);
}
return 0;
}
T3 树状数组
预处理
预处理
考虑查询,从低到高依次枚举
code
#include <cstdio>
#include <algorithm>
using namespace std;
const int max1 = 5e5;
const int inf = 0x3f3f3f3f;
int n, m, k, A, B;
int val[max1 + 5], sum[max1 + 5];
int f[max1 + 5][30][2], ans[max1 + 5], last;
int main ()
{
freopen("fenwick.in", "r", stdin);
freopen("fenwick.out", "w", stdout);
scanf("%d%d%d%d%d", &n, &m, &k, &A, &B);
for ( int i = 1; i <= n; i ++ )
scanf("%d", &val[i]);
val[n + 1] = 0;
sum[0] = 0;
for ( int i = 1; i <= n + 1; i ++ )
{
sum[i] = sum[i - 1];
if ( val[i] != -1 )
sum[i] ^= val[i];
}
f[n + 1][0][0] = n + 2; f[n + 1][0][1] = inf;
for ( int i = n; i >= 1; i -- )
{
if ( val[i] == -1 )
{
f[i][0][0] = i + 1;
f[i][0][1] = i + 1;
}
else
{
if ( !(val[i] & 1) )
{
f[i][0][0] = i + 1;
f[i][0][1] = f[i + 1][0][1];
}
else
{
f[i][0][0] = f[i + 1][0][1];
f[i][0][1] = i + 1;
}
}
}
for ( int u = 1; u <= k - 1; u ++ )
{
f[n + 1][u][0] = n + 2; f[n + 1][u][1] = inf;
for ( int i = n; i >= 1; i -- )
{
if ( val[i] == -1 )
{
f[i][u][0] = i + 1;
f[i][u][1] = i + 1;
}
else
{
f[i][u][0] = f[i][u][1] = inf;
int j = f[i][u - 1][0];
if ( j != inf )
{
if ( !(((sum[i - 1] ^ sum[j - 1]) >> u) & 1) )
f[i][u][0] = j;
else
f[i][u][0] = f[j][u][1];
}
j = f[i][u - 1][0];
if ( j != inf )
{
if ( !(((sum[i - 1] ^ sum[j - 1]) >> u) & 1) )
f[i][u][1] = f[j][u][1];
else
f[i][u][1] = j;
}
}
}
}
ans[n + 1] = 0;
for ( int i = n; i >= 1; i -- )
{
int u = -1;
for ( int j = k - 1; j >= 0; j -- )
if ( f[i][j][0] != inf )
{ u = j; break; }
if ( u == -1 )
ans[i] = sum[i - 1] ^ sum[n];
else
ans[i] = (((sum[i - 1] ^ sum[n]) >> (u + 1)) << (u + 1)) | (ans[f[i][u][0]] & ((1 << (u + 1)) - 1));
}
int L, x;
while ( m -- )
{
scanf("%d%d", &L, &x);
L = L ^ ((1LL * A * last + B) % n);
x = x ^ ((1LL * A * last + B) % (1 << k));
for ( int i = 0; i <= k - 1; i ++ )
{
if ( (x >> i) & 1 )
{
if ( f[L][i][1] == inf )
{
last = (x ^ (((sum[L - 1] ^ sum[n]) >> i) << i)) | (ans[L] & ((1 << i) - 1));
break;
}
x ^= ((sum[f[L][i][1] - 1] ^ sum[L - 1]) >> (i + 1)) << (i + 1);
x ^= 1 << i;
L = f[L][i][1];
}
}
if ( !x )
last = ans[L];
printf("%d\n", last);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】