2026-09-01~09-04 hetao1733837 的刷题记录

LGP6798 「StOI-2」简单的树

原题链接:「StOI-2」简单的树

分析

首先,我需要一个 dfn,把这棵树拍到一个序列上,然后变成了一个区间 max ⁡ \max max 问题?

对于一个点权值的修改,我们发现他似乎只会影响他的祖先,所以,我们难道要 reverse 一下 dfn 吗?那似乎......这玩意真的好做吗?

我们发现, l ′ , r ′ l',r' l′,r′ 这个区间巨大,不能每次都修改。对于那些不影响的部分,我们可以预处理一下,然后做。对于那些影响祖先的部分,我们发现这个东西依然有一个上届,且,上届似乎一直只会向根移动(为了方便,我觉得直接在 v a l val val 里讨论是正确的,诶,不完全对,如果一个点修改了......我们可以粗略证明,这个东西只会影响从其儿子开始再一次进行统计,不会影响更深的位置)。

那么,这种很区的优化可以获得随机的分数,因为我觉得出题人估计是随便卡的。

线段树精细实现可以完成吗?我把 dfn 搞到线段树上,然后......然后 G G G 了......倍增不支持修改啊😭

数学?这和数学有什么关系吗?


这个还有写的风险吗😭

T640835 【pty2022】编号

原题链接:【pty2022】编号

分析

就类似进制转换吧......🤮

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 15;
int n, k;
int a[N];
int qpow(int a, int b){
    int res = 1;
    while (b){
        if (b & 1) 
			res *= a;
        a *= a;
        b >>= 1;
    }
    return res;
}
signed main(){
	// freopen("number.in", "r", stdin);
	// freopen("number.out", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
	cout.tie(0);
    cin >> n >> k;
    for (int i = 1; i <= k; i++) 
		cin >> a[i];
    if (a[1] == 0){
        if (n == 1){
            cout << 0 << '\n';
            return 0;
        }
        n--;
        vector<int> pos;
        for (int i = 1; i <= k; i++){
        	if (a[i] != 0){
        		pos.push_back(a[i]);
			}
		}
        int m = pos.size();
        if (n <= m){
            cout << pos[n - 1] << '\n';
            return 0;
        }
        n -= m;
        int len = 2;
        while (true){
            int cnt = m * qpow(k, len - 1);
            if (n <= cnt) 
				break;
            n -= cnt;
            len++;
        }
        n--;
        int tmp1 = qpow(k, len - 1);
        int tmp2 = n / tmp1;
        n %= tmp1;
        cout << pos[tmp2];
        for (int i = len - 2; i >= 0; i--){
            int p = qpow(k, i);
            int idx = n / p;
            n %= p;
            cout << a[idx + 1];
        }
        cout << '\n';
    } 
	else{
        int m = k;
        if (n <= m){
            cout << a[n] << '\n';
            return 0;
        }
        n -= m;
        int len = 2;
        while (true){
            int cnt = qpow(m, len);
            if (n <= cnt) 
				break;
            n -= cnt;
            len++;
        }
        n--;
        for (int i = len - 1; i >= 0; i--){
            int p = qpow(m, i);
            int idx = n / p;
            n %= p;
            cout << a[idx + 1];
        }
    }
}

CF2255A Hot Potatoes at the Fairy Warehouse

原题链接:A. Hot Potatoes at the Fairy Warehouse

分析

传说是一个博弈论。

这是容易的吗(・∀・(・∀・(・∀・(

秒了!我们发现最佳的博弈是保留 k − 1 k-1 k−1 轮给下一位。做完了!

嗯😭

咋这么聪明😭

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int t;
int n, k;
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> t;
    for (int cs = 1; cs <= t; cs++){
        cin >> n >> k;
        string s;
        cin >> s;
        int cnt1 = 0, cnt2 = 0;
        for (int i = 0; i < (int)s.length(); i++){
            int j = (i + 1) % (int)s.length();
            if (s[i] == '1' && s[j] == '1'){
                if (i % 2 == 0){
                    cnt1++;
                }
                else{
                    cnt2++;
                }
            }
            if (s[i] == '1' && s[j] == '0'){
                if (i % 2 == 0){
                    cnt2++;
                }
                else{
                    cnt1++;
                }
            }
        }
        cout << cnt2 << " " << cnt1 << '\n';
    }
}

CF2255D How Long Until Nothing Remains?

原题链接:D. How Long Until Nothing Remains

分析

天啊,你会发现,这个东西最少操作 n n n 次,至多操作 n + log ⁡ 2 n n+\log_2{n} n+log2n 次。

由于这个删的太困难了,考虑 狭义 hxf ⁡ \operatorname{hxf} hxf 容斥,即 正难则反

那么,我们变成了从 0 0 0 开始加,每一次,如果选择这个数,则将其变成 a i × 2 + 1 a_{i}\times 2+1 ai×2+1,反之,变成 a i × 2 a_{i}\times 2 ai×2。由于要枚举 31 31 31 个数,常数有点大,所以,二分一下,那么,常数变成了 log ⁡ 2 31 \log_{2}{31} log231,还是非常不错的。

至于我们的 check,开一个 priority_queue,然后每次处理堆顶,做完了。

就是说,如果有一个数大于当前 ,那就出问题了,反之,我们进行一下异或,因为这个都是一次一次 × 2 \times2 ×2 弄上来的,就做完了。

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200005;
int t;
int n, a[N], pw[35];
bool cmp(int x, int val){
	if (x >= 31)
		return false;
	if (pw[x] < val)
		return true;
	return false;
}
bool check(int x){
	priority_queue<int> q;
    for (int i = 1; i <= n; i++)
        q.push(a[i]);
	while (!q.empty()){
		int tmp = q.top();
		q.pop();
		x--;
		if (x < 0)
			return false;
		if (cmp(x + 1, tmp))
			return false;
		if (cmp(x, tmp)){
			tmp ^= pw[x];
			q.push(tmp);
		}
	} 
	return true;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	pw[0] = 1;
	for (int i = 1; i < N; i++)
		pw[i] = pw[i - 1] * 2;
	for (int cs = 1; cs <= t; cs++){
		cin >> n;
		for (int i = 1; i <= n; i++){
			cin >> a[i];
		}
		int l = n, r = n + 31;
		while (l < r){
			int mid = (l + r) >> 1;
			if (check(mid)){
				r = mid;
			}
			else{
				l = mid + 1;
			}
		}
		cout << r << '\n';
	}
}

LGP1290 欧几里德的游戏

原题链接:欧几里德的游戏

分析

不是,这俩哥们有点太聪明了吧???

看得出来,一旦出现倍数关系就意味着胜负已分。

这场博弈,分明就是老鼠洗完头,你一点赢他的几率都没有!!!

泥肘!!!

那么,两个人的最优决策就是祸水东引,让对方得出倍数关系,并且让 1 1 1 出现在对自己有利的位置上。

思考一下,其实是操作的总次数的奇偶性导致的胜负,所以,对于后续,我们发现似乎总会出现每次只能减一倍的情况,所以,第一次操作的时候,我们大概就要开始卡了。但是,这俩人都不傻,所以,会遇见一些东西吗?就是会漏一次......其实感觉博弈论的题,你开始想这种东西的时候已经偏了。要不然这就是个伪科学。

算了算了,看题解吧😭

对吧,其实我想到类似余数的东西了。

有点神啊......

就是说,相当于我们认为当前是 ( x , y ) (x,y) (x,y),且 y = k x + z y=kx+z y=kx+z,则这一步可以转到 ( x , y − ( k − 1 ) x ) (x,y-(k-1)x) (x,y−(k−1)x) 也就是 ( x , x + z ) (x,x+z) (x,x+z)。

然后,考虑 k ≥ 2 k\ge 2 k≥2 的情况,这个时候当前操作者必胜,就是相当于他有更多的冗余,可以操作这个游戏的导向......应该是这样的。

对于 k < 2 k<2 k<2,那就递归下去直到出现即可。

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int C;
int n, m;
int work(int a, int b, int winner){
	if (a == b || a / b >= 2)
		return winner;
	return work(max(a - b, b), min(a - b, b), winner ^ 1);
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> C;
	for (int cs = 1; cs <= C; cs++){
		cin >> m >> n;
		int ans = work(max(n, m), min(n, m), 0);
		if (ans == 0){
			cout << "Stan wins" << '\n';
		}
		else{
			cout << "Ollie wins" << '\n';
		}
	}
}
相关推荐
Evand J1 小时前
【MATLAB例程,图像滤波5】 反谐波均值滑动窗口滤波(CHMF)图像降噪与质量评价,附代码下载链接
图像处理·算法·计算机视觉·matlab·均值算法·滑动窗口滤波·均值滑动
血小板要健康2 小时前
链表 阶段算法总结
java·数据结构·笔记·算法·leetcode·链表
a187927218312 小时前
【算法】回溯算法(三):三记重锤与 N 皇后——记忆化、状态设计与三层漏斗
算法·leetcode·go·剪枝·回溯·n皇后·算法讲解
HugoStudio_SWAN4 小时前
洛谷 P1420 / P1179 / B4262 最长连号、数字统计与词频统计——统计的三种面孔
c++·学习·程序人生·算法
青 春 记 忆4 小时前
LeetCode 350. 两个数组的交集 II|Python 解法详解
python·算法·leetcode
raindayinrain4 小时前
c++并发
c++
j7~4 小时前
【C++】智能指针的使用及其原理--详解
c++·c++11·内存泄漏·智能指针·raii·boost智能指针
阳明山水5 小时前
销量预测2025—2026:从模型竞赛到系统融合的范式转型
人工智能·深度学习·算法·机器学习·架构
桐盛科技6 小时前
拒绝“漂绿”风险:基于边缘计算的碳排放数据清洗算法与实时校验逻辑
人工智能·算法·边缘计算