2026-04-12~14 hetao1733837 的刷题记录

2026-04-12~13 hetao1733837 的刷题记录

04-12

LGP4799 [CEOI 2015] 世界冰球锦标赛 (Day2)

原题链接:[CEOI 2015] 世界冰球锦标赛 (Day2)

分析

不是等一下,这种和的东西......背包?那不炸我吃!这个太大了......思考类比 NOIP2025T1 ,发现好像并不一样......

观察到 N N N 小的可怜,所以,考虑爆搜......好像真的可以!我宕机一下......那似乎还要搞一点组合数......又复杂了......就是把相同的搓成一堆......思考一下......

好的,场上的话,不会 折半搜索 可以打一个爆搜,打一个背包,这样理论上获得了 70pts 的好成绩。

考虑正解------折半搜索。

这么聪明!我们爆搜前一部分和后一部分,搞出来所有可能的和,然后,把其中一个排序,另外一个直接遍历,然后,与 m m m 做差,在第一个里面二分,即可统计答案!

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 50;
int n, mid;
long long m, inp[N];
vector<long long> suma, sumb;
void dfsa(int L, int R, long long sum){
    if (sum > m) 
        return ;
    if (L > R){
        suma.push_back(sum);
        return ;
    }
    dfsa(L + 1, R, sum + inp[L]);
    dfsa(L + 1, R, sum);
}
void dfsb(int L, int R, long long sum){
    if (sum > m) 
        return ;
    if (L > R){
        sumb.push_back(sum);
        return ;
    }
    dfsb(L + 1, R, sum + inp[L]);
    dfsb(L + 1, R, sum);
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    mid = n / 2;
    for (int i = 1; i <= n; i++){
        cin >> inp[i];
    }
    dfsa(1, mid, 0);
    dfsb(mid + 1, n, 0);
    sort(suma.begin(), suma.end());
    long long ans = 0;
    for (auto v : sumb){
        ans += upper_bound(suma.begin(), suma.end(), m - v) - suma.begin();
    }
    cout << ans;
}

04-13

LGP2119 [NOIP 2016 普及组] 魔法阵

原题链接:[NOIP 2016 普及组] 魔法阵

分析

显然有一个 O ( m 4 ) O(m^4) O(m4) 左右的暴力。感觉可以套一坨二分......但是,显然比较复杂。思考一下正解🤔

但是,tag 里给了 mathematics,就很微妙了。

思考一下......

拆一下......

要求 X a < X b < X c < X d X_a<X_b<X_c<X_d Xa<Xb<Xc<Xd,且 X b − X a = 2 X d − 2 X c X_b-X_a=2X_d-2X_c Xb−Xa=2Xd−2Xc,且 X b − X a < X c 3 − X b 3 X_b-X_a<\frac{X_c}{3}-\frac{X_b}{3} Xb−Xa<3Xc−3Xb,即 4 X b 3 < X c + 3 X a 3 \frac{4X_b}{3}<\frac{X_c+3X_a}{3} 34Xb<3Xc+3Xa,即 4 X b < X c + 3 X a 4X_b<X_c+3X_a 4Xb<Xc+3Xa。

总结为
X a < X b < X c < X d , X b − X a = 2 X d − 2 X c , 4 X b < X c + 3 X a X_a<X_b<X_c<X_d,X_b-X_a=2X_d-2X_c,4X_b<X_c+3X_a Xa<Xb<Xc<Xd,Xb−Xa=2Xd−2Xc,4Xb<Xc+3Xa

我不会/ll

我要看题解/ll
O ( m 4 ) O(m^4) O(m4) 居然有 50 p t s 50pts 50pts😱

然后排个序就 60 p t s 60pts 60pts 了😱

发现,设一些未知数,得出
X a + 2 t = X b , X b + 6 t + k = X c , X c + t = X d X_a+2t=X_b,X_b+6t+k=X_c,X_c+t=X_d Xa+2t=Xb,Xb+6t+k=Xc,Xc+t=Xd

设 k = 1 k=1 k=1,限制 X d X_d Xd 即可确定剩余几个,即可统计答案。 O ( n 2 ) O(n^2) O(n2) 能过?我**************************

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 15005, M = 40005;
int n, m, X[M];
int ans[M][5];
int buc[N];
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= m; i++){
		cin >> X[i];
		buc[X[i]]++;
	}
	for (int t = 1; t * 9 <= n - 2; t++){
		for (int xd = 9 * t + 2, tot = 0; xd <= n; xd++){
			int xa = xd - 9 * t - 1;
			int xb = xa + 2 * t;
			int xc = xd - t;
			tot += buc[xa] * buc[xb];
			ans[xc][3] += tot * buc[xd];
			ans[xd][4] += tot * buc[xc];
		}
		for (int xa = n - 9 * t -1, tot = 0; xa >= 1; xa--){
			int xb = xa + 2 * t;
			int xc = xb + 6 * t + 1;
			int xd = xc + t;
			tot += buc[xc] * buc[xd];
			ans[xa][1] += tot * buc[xb];
			ans[xb][2] += tot * buc[xa];
		}
	}
	for (int i = 1; i <= m; i++){
		cout << ans[X[i]][1] << " " << ans[X[i]][2] << " " << ans[X[i]][3] << " " << ans[X[i]][4] << '\n';
	}
}

04-14

LGP7703 「MCOI-09」Dream and Strings REMATCH

原题链接:「MCOI-09」Dream and Strings REMATCH

分析

见到了算是缘分吧......

感觉会有一定的启发价值。

竟没有 tag ⁡ \operatorname{tag} tag!

好的,那么一个 O ( 3 n ) O(3^n) O(3n) 的爆搜呼之欲出!发现 5000 ≤ N ≤ 10 5 T 5000 \le N \le \frac{10^5}{T} 5000≤N≤T105,我已急哭/ll
a i ≤ 10 18 a_i\le 10^{18} ai≤1018,背包也无法实现/ll

难道搞一个动态匹配的状物?一边为 1 1 1,则......

我干嘛要这样呢?我可以把一坨东西整成 0 0 0,当序列有重复时,就可以很爽了。问题在于不是怎么办......

显然,这题的复杂度要求不超过 O ( ∑ N l o g ∑ N ) O(\sum{N}log\sum{N}) O(∑Nlog∑N),那 ......难道我蒙一个基准值,然后硬凑?那好像至少 O ( n 2 ) O(n^2) O(n2) 啊......
其实,数据随机,我们可以直接交足够多的次数使得题目通过......

怎么办/ll

根据我巧妙地计算, O ( T ( ∑ n ) 2 ) O(T({\sum{n}})^2) O(T(∑n)2) 似乎可以过......因为我们可以进行一些巧妙地推到。

好吧,这个想法并不成熟。折半搜索用不了......

严肃决定打开题解......俺妈一会给我送东西(●'◡'●)
呃,升序排序后相邻两个配对相减,然后就做完了。

对,很简洁,复杂度证明基于其期望和一坨啊吧啊吧,得出复杂度来到了 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)。

实现上,对于每个值,维护两个集合,一个表示加这个值,另一个表示减这个位置的值,就是另外一些位置吧,如果一旦发现两个值相等,那么直接结束操作,然后把两个位置随即搞一搞,即可得出答案。

若不想等,假设 a < b a<b a<b,则要 b − a b-a b−a,那么,减 b b b 的集合和加 a a a 的集合合并,另外的两个集合同理。

严肃观看题解代码。

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005;
int T;
int n;
struct node{
    int val;
    set<int> add, rec;
    bool operator<(const node k) const{
        return val < k.val;
    }
}a[N];
int ans[N];
node merge(node x, node y){
    for (auto v : y.add){
        x.rec.insert(v);
    }
    for (auto v : y.rec){
        x.add.insert(v);
    }
    x.val -= y.val;
    return x;
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> T;
    for (int cs = 1; cs <= T; cs++){
        cin >> n;
        int tmp = n;
        for (int i = 1; i <= n; i++){
            cin >> a[i].val;
            a[i].add.clear();
            a[i].rec.clear();
            a[i].add.insert(i); 
            ans[i] = 0;
        }
        bool flag = false; 
        while (n){
            int m = n >> 1;
            sort(a + 1, a + n + 1);
            for (int i = 1; i <= m; i++){
                if (a[i * 2 - 1].val == a[i * 2].val){
                    flag = true;
                    for (auto v : a[i * 2 - 1].add) 
                        ans[v] = 1;
                    for (auto v : a[i * 2 - 1].rec) 
                        ans[v] = -1;
                    for (auto v : a[i * 2].add) 
                        ans[v] = -1;
                    for (auto v : a[i * 2].rec) 
                        ans[v] = 1;
                    break;
                }
            }
            if (flag) 
                break;
            for (int i = 1; i <= m; i++){
                a[i] = merge(a[i * 2], a[i * 2 - 1]);
            }
            n >>= 1;
        }
        if (!flag){
            cout << -1;
        }
        else{
            for (int i = 1; i <= tmp; i++){
                cout << ans[i] << " ";
            }
        }
        cout << '\n';
    }
}

最开始 merge 的位置写错了,所以全都 WA 了。

相关推荐
BestOrNothing_201521 小时前
C++零基础到工程实战(3.6):逻辑实战示例—日志模块
c++·命令行参数·main函数·switch case·逻辑判断·if else·enum class
t***54421 小时前
有哪些常见的架构设计模式在现代C++中应用
开发语言·c++
米粒11 天前
力扣算法刷题 Day 42(股票问题总结)
算法·leetcode·职场和发展
zopple1 天前
汇编、C、C++和Java核心技术对比
c语言·汇编·c++
汉克老师1 天前
GESP2024年3月认证C++三级( 第三部分编程题(1、字母求和)
c++·string·gesp三级·gesp3级·大小写判断
沐雪轻挽萤1 天前
10. C++17新特性-保证的拷贝消除 (Guaranteed Copy Elision / RVO)
开发语言·c++
leaves falling1 天前
C/C++ 的内存管理,函数栈帧详讲
java·c语言·c++
wuyoula1 天前
AI导航智能决策系统源码 附教程
c++·tcp/ip·源码
浅念-1 天前
从LeetCode入门位运算:常见技巧与实战题目全解析
数据结构·数据库·c++·笔记·算法·leetcode·牛客
CoovallyAIHub1 天前
无人机拍叶片→AI找缺陷:CEA-DETR改进RT-DETR做风电叶片表面缺陷检测,mAP50达89.4%
算法·架构·github