2026CSP-S模拟13
写在前面
Yuki 酱萌萌的!

强烈谴责 JS 在 Rain 写卸载签面の时候说“又在写了”之类的话qwq………
推歌:由于赛时把 camera 看成了 cinema,但是因为找不到相应的链接于是请自行搜索《Cinema》feat.VBS。
T1 完全平方数
简单题。
发现完全平方数只有 \(O(\sqrt{n})\) 个,而 \(1≤n≤10 ^{12}\) ,于是可以非常舒适地枚举完全平方数。
大概就是乘法原理大力统计每个数能被多少个区间覆盖,然后累加答案,注意取模,开龙龙。
Code

#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
#define int long long
int n, ans;
signed main(){
freopen("square.in", "r", stdin);
freopen("square.out", "w", stdout);
ios :: sync_with_stdio(0), cin. tie(0), cout. tie(0);
cin >> n;
int rain = 1;
for(; rain * rain <= n; rain ++){
ans = (ans + (rain * rain % mod) * ((n - (rain * rain) + 1 + mod) % mod) % mod) % mod;
}
cout << ans;
return 0;
}
T2 星际跃迁
感谢 Huge 的玩 checker 奶妈式教程,感谢大家让肝硬化蹭到了学习使用 checker 的机会!
简单构造。
这个 \(1≤X≤10^{18}\) 和 \(n≤62\) 很美丽喵!
那么肯定是在老哥方面做文章,注意到根本没限制边数,更加舒适。
于是把二的整数次幂玩出来然后发现是个完全图,之后这张图每删一条边减少的路径数量就是它前面的路径数乘它后面的路径数,很难受,于是我们只杀掉与起点相连的,发现每次减少 \(2^k\) 于是做完了。
Code

#include <bits/stdc++.h>
using namespace std;
const int _ = 10086;
long long x, er[66];
int n, m;
struct hhh{
int x, y;
}ans[_];
int main(){
freopen("wander.in", "r", stdin);
freopen("wander.out", "w", stdout);
ios :: sync_with_stdio(0), cin. tie(0), cout. tie(0);
cin >> x;
int lg = __lg(x);
if(((__int128)1 << lg) != x){
lg ++;
}
cout << lg + 2 << ' ';
x = ((__int128)1 << lg) - x;
er[lg + 1] = 1;
for(int i = lg; i >= 2; i --){
er[i] = er[i + 1] << 1;
}
for(int i = 1; i <= lg + 1; i ++){
for(int j = i + 1; j <= lg + 2; j ++){
if(i == 1){
if(j != lg + 2 && (er[j] & x)){
continue;
}
}
ans[++ m] = {i, j};
}
}
cout << m << '\n';
for(int i = 1; i <= m; i ++){
cout << ans[i]. x << ' ' << ans[i]. y <<'\n';
}
return 0;
}
Delta的疑惑
这题如果打的边双那么会得到 0 pts,点双可以获得 100 pts,但是肝硬化赛时发明出了《无向图强连通分量》于是牠荣获了 45 pts。
我们至今不知道这个 LCA 同志如何使用这么神人的做法跑过 \(1≤n≤10^5,0≤m≤10^6\) 的,反正我大概会写成 \(O(n*操作数)\) 在看到 WA 之前先 TLE………
但是这只是一道题中题,现在我们要判断 LCA 同志的假做法能通过什么样的数据,不能通过什么样的数据。
一顿手玩可以发现,在一个点双里,如果存在两个点之间没有直接相连的路径那么我们可以构造一种 LCA 同志的做法会恰好把它俩剩下然后跑两遍,而正解会将其拆分然后刚好直接取完的东西。
但是如果这个点双是完全图(任意两点都直接有边相连),那么就卡不掉。
于是就愉快地做出来了,难点在于 Tarjan 的发明,发明对了就对了,没对就像肝硬化一样满地乱哭当小丑去吧。
Code

#include <bits/stdc++.h>
using namespace std;
const int _ = 1000010;
int root, niumo, du[_], dfn[_], low[_], cur, s[_], top, cnt, n, m, x, y, to[_ << 1], nxt[_ << 1], h[_], tot = 1;
bool v[_];
vector<int> miao[_];
inline void add(int x, int y){
to[++ tot] = y;
nxt[tot] = h[x];
h[x] = tot;
return ;
}
inline void tarjan(int x){
dfn[x] = low[x] = ++ niumo;
s[++ top] = x;
if(x == root && h[x] == 0){
miao[++ cnt]. emplace_back(x);
return ;
}
for(int i = h[x]; i; i = nxt[i]){
int y = to[i];
if(! dfn[y]){
tarjan(y);
low[x] = min(low[x], low[y]);
if(dfn[x] <= low[y]){
cnt ++;
do{
miao[cnt]. emplace_back(s[top]);
}while(s[top --] != y);
miao[cnt]. emplace_back(x);
}
}
else{
low[x] = min(low[x], dfn[y]);
}
}
return ;
}
int main(){
freopen("delta.in", "r", stdin);
freopen("delta.out", "w", stdout);
ios :: sync_with_stdio(0), cin. tie(0), cout. tie(0);
cin >> n >> m;
for(int i = 1; i <= m; i ++){
cin >> x >> y;
add(x, y), add(y, x);
du[x] ++, du[y] ++;
}
for(int i = 1; i <= n; i ++){
if(! dfn[i]){
top = 0;
root = i;
tarjan(i);
}
}
for(int i = 1; i <= cnt; i ++){
for(int j = 0; j < miao[i]. size(); j ++){
du[miao[i][j]] -= miao[i]. size() - 1;
}
}
for(int i = 1; i <= n; i ++){
if(du[i]){
cout << "WA";
return 0;
}
}
cout << "AC";
return 0;
}
T4 魔法相机
题解会用最简洁【并非】最生动【也不是】最准确的语言诉说一切。



Code

#include <bits/stdc++.h>
using namespace std;
const int _ = 200010;
int n, s, rt, mxt, cnt;
struct hhh{
int l, r;
}a[_];
struct xxx{
int op, p;
inline bool operator <(const xxx & x)const{
if(p ^ x. p){
return p > x. p;
}
return op > x. op;
}
};
inline int tim(long long v){
if(v < 0){
return - 1;
}
if(v > mxt){
return mxt;
}
return (int)v;
}
priority_queue<xxx> q;
#define ls(x) tree[(x)]. ls
#define rs(x) tree[(x)]. rs
#define mx(x) tree[(x)]. mx
#define l(x) tree[(x)]. l
#define mid ((l + r) >> 1)
struct rain{
int mx, l, ls, rs;
}tree[_ << 5];
inline void pushup(int root){
mx(root) = l(root) + max(mx(ls(root)), mx(rs(root)));
return ;
}
inline void update(int & root, int l, int r, int x, int y){
if(x > y){
return ;
}
if(! root){
root = ++ cnt;
}
if(x <= l && r <= y){
mx(root) ++, l(root) ++;
return ;
}
if(x <= mid){
update(ls(root), l, mid, x, y);
}
if(y > mid){
update(rs(root), mid + 1, r, x, y);
}
pushup(root);
return ;
}
inline void pointSet(int & root, int l, int r, int p, int v){
if(root == 0){
root = ++ cnt;
}
if(l == r){
mx(root) = v;
return ;
}
if(p <= mid){
pointSet(ls(root), l, mid, p, v);
}
else{
pointSet(rs(root), mid + 1, r, p, v);
}
pushup(root);
return ;
}
inline int query(int root, int l, int r, int x, int y){
if(root == 0 || x > y){
return 0;
}
if(x <= l && r <= y){
return mx(root);
}
int as = 0;
if(x <= mid){
as = max(as, query(ls(root), l, mid, x, y));
}
if(y > mid){
as = max(as, query(rs(root), mid + 1, r, x, y));
}
return as + l(root);
}
inline bool addp(int p, bool op){
if(p < 0){
return 0;
}
int a = query(rt, 0, mxt, 0, tim(1LL * p - s - 1));
int b = query(rt, 0, mxt, 0, tim(1LL * p - s));
if(! op && b <= a){
return 0;
}
pointSet(rt, 0, mxt, p, b);
q. emplace((xxx){- 2, tim(1LL * p + s)});
return 1;
}
int main(){
freopen("camera.in", "r", stdin);
freopen("camera.out", "w", stdout);
ios :: sync_with_stdio(0), cin. tie(0), cout. tie(0);
cin >> n >> s;
for(int i = 1; i <= n; i ++){
cin >> a[i]. l >> a[i]. r;
if(a[i]. r < 0){
i --, n --;
continue;
}
a[i]. l = max(a[i]. l, 0);
q. emplace((xxx){a[i]. l, a[i]. r});
q. emplace((xxx){- 1, a[i]. l});
mxt = max(mxt, a[i]. r);
}
// cout << q. size() << ' ';
int bfr = - 1;
while(q. size()){
xxx nw = q. top();
q. pop();
if(nw. op >= 0){
update(rt, 0, mxt, nw. op, nw. p);
continue;
}
if(nw. p == bfr){
continue;
}
if(addp(nw. p, nw. op == -1)){
bfr = nw. p;
}
}
cout << mx(rt);
return 0;
}

The End.
本文来自博客园,作者:养鸡大户肝硬化,转载请注明原文链接:https://www.cnblogs.com/rain20100708/p/22508263

我并不能发明出正确的塔尖
浙公网安备 33010602011771号