河南萌新联赛2025第(五)场:信息工程大学”
目录
- A-宇宙终极能量调和与多维时空稳定性验证下的基础算术可行性研究
- 解题思路
- AC代码
- B-中位数
- 解题思路
- AC代码
- C-中位数+1
- 解题思路
- AC代码
- F-中位数+4
- 解题思路
- AC代码
- G-简单题
- 解题思路
- AC代码
- I-Re:从零开始的近世代数复习(easy)
- 解题思路
- AC代码
- K-狂飙追击
- 解题思路
- AC代码
包含ABCFGIK题
A-宇宙终极能量调和与多维时空稳定性验证下的基础算术可行性研究
解题思路
天呐!
大水体还这么长,真是不想看,大致了解了下题目内容,α 的本征值为 1 ,β 的本征值为 1 ,虽然α(代表正能量基元)和 β(代表负能量基元),但是严格遵循MSEFM模型和泽塔稳定性第一定律,不受外界影响,输出二者之和2即可。
AC代码
void solve()
{cout<<2;
}
B-中位数
解题思路
可以发现不管怎么选,到最后剩下的两个一定是最大值和最小值,因此只需要输出二者的平均值,小数向下取整。
AC代码
void solve()
{cin>>n;for(int i=1;i<=n;i++)cin>>a[i];sort(a+1,a+1+n);cout<<(a[1]+a[n])/2;
}
C-中位数+1
解题思路
这简直就是模板中的模板题,B题还没看就先做这个了用对顶堆依次求中位数即可。如果是第奇数个,输出大顶堆堆顶,否则输出二者堆顶的平均值向下取整。
不会对顶堆的请看我的这篇博客:堆和优先对列,具体选择求中位数的那部分看。
AC代码
priority_queue<int,vector<int>>l;
priority_queue<int,vector<int>,greater<int>>r;
void solve()
{cin>>n;for(int i=1;i<=n;i++){cin>>a[i];if(l.size()==0||a[i]<l.top())l.push(a[i]); elser.push(a[i]);if(l.size()>r.size()+1)r.push(l.top()),l.pop();else if(l.size()<r.size())l.push(r.top()),r.pop();if(i%2==1) cout<<l.top()<<" ";else{int ans=l.top()+r.top();cout<<ans/2<<" ";}}
}
F-中位数+4
题目来源
解题思路
这就是一个简单的进制转化问题,统计下尾部的0即可。
AC代码
int Jin(int n,int k)
{int ans=0;char s;while(n){s=n%k+'0';n/=k;if(s=='0')ans++;else break;}return ans;
}
void solve()
{cin>>n>>k;int an=Jin(n,k);cout<<an;
}
G-简单题
题目来源
解题思路
说是简单题,实则,如果你想偏了那将很难A下这题,因为题中所给的行列式,也许你能推出它的规律,但他的计算并不是简单的相加,我一开始就把它想成了相加,结果一直WA就换了个思路,题中已经给出了f(1)=1,f(2)=1,f(3)=2,其实他就是一个斐波那契数列,满足
f[i]=f[i-1]+f[i-2]
那么通过打表观察F[i]的值,可以看到满足三个一循环,如果i%3==1他的和就是奇数输出1,否则就是偶数输出0.
主要还是没学过线性代数,吃了亏,原来这就是一个行列式的展开。
AC代码
void solve()
{cin>>n;if(n%3==1)cout<<1;else cout<<0;
}
I-Re:从零开始的近世代数复习(easy)
题目来源
解题思路
这道题思路是有的,朴素的写法也写出来了,果然运行超时,
其实就是最近公共祖先想不起来了哈。
部分伪代码
// 预处理阶段
int f[N][25], g[N][25], dep[N];
void dfs_init(int u, int fa) {dep[u] = dep[fa] + 1;f[u][0] = fa;g[u][0] = a[u]; // 假设a[u]是节点u的复习时间for (int i = 1; i <= 20; i++) {f[u][i] = f[f[u][i-1]][i-1]; g[u][i] = g[u][i-1] + g[f[u][i-1]][i-1]; }for (auto v : e[u]) {dfs_init(v, u);}
}// 查询阶段
int query_lca(int x, int y) {int res = 0;if (dep[x] < dep[y]) swap(x, y);// 把x提到和y同深度,同时累加时间for (int i = 20; i >= 0; i--) {if (dep[f[x][i]] >= dep[y]) {res += g[x][i];x = f[x][i];}}if (x == y) return res + g[x][0]; // 加上x本身的时间(或根据题意调整)// 同时上跳x和y,累加路径时间for (int i = 20; i >= 0; i--) {if (f[x][i] != f[y][i]) {res += g[x][i] + g[y][i];x = f[x][i];y = f[y][i];}}res += g[x][0] + g[y][0]; // 加上x、y到LCA的最后一步return res;
}
-
路径和计算范围:
最终结果 = 根节点(1号)的值 + x到LCA的路径和 + y到LCA的路径和 +(若LCA不是根,则加上LCA到根的路径和)。 -
lca
函数的双重作用:
不仅用于寻找最近公共祖先,还在寻找过程中实时累加路径和到全局变量ans
,避免二次计算。 -
二进制倍增的优势:
无论是提升节点到同一深度,还是寻找LCA,都通过2^k
级跳跃实现,将单次查询复杂度控制在O(log n)
,确保大数据量下不超时。
AC代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=1e5+6;
vector<int>e[N];
int dep[N],f[N][25],g[N][25],ans;
void dfs(int u,int fa)
{dep[u]=dep[fa]+1;f[u][0]=fa;for(int k=1;k<=20;k++){f[u][k]=f[f[u][k-1]][k-1];g[u][k]=g[u][k-1]+g[f[u][k-1]][k-1];}for(auto c:e[u])dfs(c,u);
}
int lca(int x,int y)
{if(dep[x]<dep[y])swap(x,y);for(int k=20;k>=0;k--){if(dep[f[x][k]]>=dep[y]){ans+=g[x][k];x=f[x][k];}}if(x==y)return x;for(int k=20;k>=0;k--){if(f[x][k]!=f[y][k]){ans+=g[x][k]+g[y][k];x=f[x][k];y=f[y][k];}}ans+=g[x][0]+g[y][0];return f[x][0];
}
void solve()
{int n;cin>>n;for(int i=1;i<=n;i++)cin>>g[i][0];for(int i=1;i<n;i++){int u,v;cin>>u>>v;e[u].push_back(v);}dfs(1,0);int q;cin>>q;while(q--){int k,x,y;cin>>k>>x>>y;ans=g[1][0];int l=lca(x,y);if(l!=1)lca(l,1);cout<<ans<<endl; }
}
signed main()
{IOS;int _=1;
// cin>>_;while(_--)solve();return 0;
}
K-狂飙追击
题目来源
解题思路
这道题我是逆序模拟来做的。
题目要求计算从起点 (sx, sy) 到目标点 (tx, ty) 的最少移动次数,移动规则是:
在当前位置 (x, y) 时,m = max(x, y),只能移动到(x + m, y)
或(x, y + m)
。
从目标点(tx, ty)
反推回起点(sx, sy)
。
当逆向推导到的坐标与起点完全一致时,说明已找到路径,输出步数并结束程序。
如果逆向推导时tx
小于 sx 或 ty小于 sy,说明不可能到达起点,输出-1
。
然后就是分tx>ty和ty>tx的情况讨论,直接除tx/ty求次数更高效,同时要记录ans步数。
AC代码
void solve()
{int ans=0;cin>>sx>>sy>>tx>>ty;while(1){if(tx==sx&&ty==sy){cout<<ans;return ;}if(tx<sx||ty<sy){cout<<-1;return ;}if(tx>ty){if(tx-sx>ty){int k=(tx-sx)/ty;tx-=k*ty;ans+=k; } else{tx-=ty;ans++;}}else if(ty>tx){if(ty-sy>tx){int k=(ty-sy)/tx;ty-=k*tx;ans+=k; } else{ty-=tx;ans++;}}else{cout<<-1;return ;}}
}