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';
		}
	}
}
相关推荐
倒头就睡的小比特4 天前
算法竞赛C++常用的STL
c++·算法
weilx12344 天前
C++笔记-文件IO-<fcntl.h>
c++
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼4 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
Smileyqp沛沛4 天前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车4 天前
C/C++ 为什么需要编译器?
开发语言·c++
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark4 天前
大规模并行计算中的负载均衡算法研究4
算法
吞下星星的少年·-·4 天前
C++ 萌新语法入门篇
c++·算法比赛
Because_of_Her14 天前
并查集-听课笔记
笔记·算法·并查集