2026-09-18 hetao1733837 的刷题记录

致敬先辈!

不过,还有就是,明天,我的最后一个完整的 O I OI OI 赛季就正式开始了。

从 2023-05-20 开始,走过了多久呢?又还要走多久呢?或者,又还能走多久?

AT_arc151_b ARC151B A < AP

原题链接:ARC151B A < AP

分析

别急,它好像每次只关心两个位置。

所以,我不放进行一些比较好看的表示,设 d p i dp_{i} dpi 表示对于所有 j < i j < i j<i 的 j j j,都有 A j = A P j A_j=A_{P_j} Aj=APj,而在 i i i 位置上有 A i < A P i A_{i}<A_{P_i} Ai<APi,那么,每次计算大概是一个,别急,这个真的可以方便地转移吗?

难道说我建一个图,每次再添加边,拿一个并查集维护吗?

我感觉这个式子在一些方面是对的。

真的是建模😭


为啥每次都想不到正解呢?

哦,有一个 A i < A P i A_i<A_{P_i} Ai<APi 就有一个 A i > A P i A_i>A_{P_i} Ai>APi,减去相等的就行了😭

那么,我们建图,有多少个连通块,就有多少个可能的取值。

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std; 
const int N = 200005;
int n, m, p[N];
int qpow(int a, int b){
	int res = 1;
	while (b){
		if (b & 1)
			res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}
int fa[N];
bool vis[N];
int find(int x){
	return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}
void merge(int x, int y){
	x = find(x);
	y = find(y);
	if (x == y)
		return ;
	fa[x] = y;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i =1; i <= n; i++){
		fa[i] = i; 
	}
	for (int i = 1; i <= n; i++){
		cin >> p[i];
		merge(i, p[i]);
	}
	int cnt = 0;
	for (int i = 1; i <= n; i++){
		vis[find(i)] = true;
	}
	for (int i = 1; i <= n; i++){
		cnt += vis[i];
	}
	cout << (qpow(m, n) - qpow(m, cnt) + mod) % mod * qpow(2, mod - 2) % mod;
	return 0;
}

初赛日 五味杂陈

AT_arc151_c ARC151C 01 Game

原题链接:ARC151C 01 Game

分析

这场可以啊,有数数,还有博弈论!写一下这个博弈论吧。

要凑的就是 0 1 的状物,所以,双方都会这么干,然后,一旦出现什么之类的东西,那么,就有一方具有必胜策略了。

我们来细想一下......

别急,难道是看 m − 1 m-1 m−1 的奇偶性吗?

并非,所以,应该是两边是 0···0 的,Takahashi 必胜;对于两边是 0···1 的,Aoki 必胜。


咋是 Nim 博弈啊😭

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
long long n, x[N];
int m, y[N];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    x[0] = 0;
    x[m + 1] = n + 1;
    for (int i = 1; i <= m; i++){
        cin >> x[i] >> y[i];
    }
    long long sg = 0;
    for (int i = 0; i <= m; i++){
        long long len = x[i + 1] - x[i] - 1;
        if (i == 0 && i == m){
            sg ^= len % 2;
        } 
        else if (i == 0 || i == m){
            sg ^= len;
        } 
        else if (y[i] == y[i + 1]){
            sg ^= 1;
        }
    }
    if (sg != 0) 
        cout << "Takahashi";
    else 
        cout << "Aoki";
    return 0;
}
相关推荐
h39744 小时前
DirectShow过滤器开发-视频源过滤器
c++·windows·音视频·directshow
程序猿编码5 小时前
榨干 RTX5090 算力!Qwen3 专用单卡推理引擎,手写C++/CUDA 算子实现 MTP 推测解码
开发语言·c++·大模型推理·qwen3·多模态推理
西飘客6 小时前
vs 怎么根据dll 生成lib文件
c++·qt
程序员老陆7 小时前
深入理解 C++ thread_local:线程私有存储的正确打开方式
开发语言·c++·程序设计
信奥卷王7 小时前
[GESP202609 六级] 分树规划
算法
夏幻灵7 小时前
LeetCode 21:合并两个有序链表——双指针与哑节点详解
算法·leetcode·链表
徐小黑ACG9 小时前
Golang 基础05 结构体struct
开发语言·算法·golang
Navigator_Z9 小时前
LeetCode //C - 1286. Iterator for Combination
c语言·算法·leetcode
北极有牛10 小时前
cpp学习笔记--常量指针
java·开发语言·算法