Solutions - 板刷 UOJ 小记
开始板刷 UOJ!
UOJ #1. A + B Problem
AC Time:2026-04-16 16:23:16
全 UOJ 最难题!(
#include <bits/stdc++.h>
using namespace std;
int main(){
int a, b;
cin >> a >> b;
cout << a+b;
return 0;
}
UOJ #2. 【NOI2014】起床困难综合症
AC Time:2026-04-16 17:25:07
比较基础的题了。
发现每一位是独立的,我们先预处理出每一位选 \(0\) 或 \(1\),运算以后最后的值。然后就可以用一种类似数位 DP 的方式搞了。
然后做完了。
复杂度:\(\mathrm O(n \log V)\),\(V\) 为值域。
UOJ #3. 【NOI2014】魔法森林
AC Time:2026-03-23 17:53:34
这题在我板刷 UOJ 之前就 A 了,为了完整性放在这里。
枚举 A 的最大值,维护在 A 的最大值取某个值的情况下 B 的 MST,发现是一个动态加边 MST,用 LCT 维护。
然后做完了。\(\mathrm O(n \log n)\)。实现的时候为了方便维护可以把边转换成点。
#include <bits/stdc++.h>
#define llong long long
#define N 200005
using namespace std;
#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
x = 0; int w = 1;
char ch = gc();
while(ch < '0' || ch > '9'){
if(ch == '-') w = -w;
ch = gc();
}
while(ch >= '0' && ch <= '9')
x = (x<<3)+(x<<1)+(ch^48), ch = gc();
x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
return read(x), read(y...);
}
int n, m, ans = 1e9+7;
struct Edge{
int u, v, w1, w2;
};
Edge G[N];
typedef pair<int, int> Node;
int son[N][4], fa[N], id[N], tag[N];
Node val[N];
int tmp[N], top;
#define get(x) (son[fa[x]][0] == x ? 0 : (son[fa[x]][1] == x ? 1 : 2))
inline void pushup(int x){
val[x] = max({val[son[x][0]], val[son[x][1]], make_pair(G[id[x]].w2, id[x])});
return;
}
inline void addtag(int x){
swap(son[x][0], son[x][1]);
tag[x] ^= 1;
return;
}
inline void pushdown(int x){
if(!tag[x]) return;
addtag(son[x][0]), addtag(son[x][1]);
tag[x] = 0;
return;
}
inline void rotate(int y){
int x = fa[y], k = get(y);
son[fa[x]][get(x)] = y, fa[y] = fa[x];
son[x][k] = son[y][k^1], fa[son[y][k^1]] = x;
son[y][k^1] = x, fa[x] = y;
pushup(x), pushup(y);
return;
}
inline void splay(int x){
int now = x;
tmp[top = 1] = now;
while(get(now) != 2) tmp[++top] = now = fa[now];
while(top) pushdown(tmp[top--]);
while(get(x) != 2){
if(get(fa[x]) != 2)
rotate(get(x) == get(fa[x]) ? fa[x] : x);
rotate(x);
}
return;
}
inline void access(int x){
for(int y = 0; x; x = fa[y = x])
splay(x), son[x][1] = y, pushup(x);
return;
}
inline void makeroot(int x){
access(x);
splay(x);
addtag(x);
return;
}
inline int find(int x){
access(x);
splay(x);
pushdown(x);
while(son[x][0]) pushdown(x = son[x][0]);
splay(x);
return x;
}
inline void split(int x, int y){
makeroot(x);
access(y);
splay(y);
}
inline void link(int x, int y){
access(x);
makeroot(x);
splay(x);
fa[x] = y;
return;
}
inline void cut(int x, int y){
makeroot(x);
access(y);
splay(y);
son[y][0] = fa[x] = 0;
pushup(y);
return;
}
int main(){
read(n, m);
for(int i = 1; i <= m; ++i)
read(G[i].u, G[i].v, G[i].w1, G[i].w2);
sort(G+1, G+m+1, [&](Edge o1, Edge o2){return o1.w1 < o2.w1;});
for(int i = 1; i <= m; ++i)
id[i+n] = i, val[i+n] = make_pair(G[i].w2, i);
for(int i = 1; i <= m; ++i){
int u = G[i].u, v = G[i].v;
if(find(u) != find(v)){
link(u, i+n);
link(v, i+n);
}
else{
split(u, v);
splay(u);
if(val[u].first > G[i].w2){
int j = val[u].second;
cut(G[j].u, j+n);
cut(G[j].v, j+n);
link(u, i+n);
link(v, i+n);
}
}
if(find(1) == find(n)){
split(1, n);
splay(1);
ans = min(ans, G[i].w1+val[1].first);
}
}
if(ans > 1e9) puts("-1");
else printf("%d", ans);
return 0;
}
UOJ #4. 【NOI2014】消除游戏
提交答案题不想做。
UOJ #5. 【NOI2014】动物园
AC Time:2026-04-16 21:06:11
发现题目要求每个点在 fail 树上最大的不大于 \(\lfloor \frac i 2 \rfloor\) 的祖先,于是倍增跳祖先即可。
#include <bits/stdc++.h>
#define llong long long
#define N 1000006
using namespace std;
constexpr llong p = 1000000007;
char a[N];
int nxt[N], dep[N], to[N][21];
int n; llong res = 1;
void _init(){
res = 1;
}
int _main(){
scanf("%s", a+1);
n = strlen(a+1);
dep[1] = 1;
for(int i = 2; i <= n; ++i){
nxt[i] = nxt[i-1];
while(nxt[i] && a[nxt[i]+1] != a[i]) nxt[i] = nxt[nxt[i]];
if(a[nxt[i]+1] == a[i]) ++nxt[i];
dep[i] = dep[nxt[i]]+1;
}
for(int i = 1; i <= n; ++i) to[i][0] = nxt[i];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= 20; ++j)
to[i][j] = to[to[i][j-1]][j-1];
for(int i = 1; i <= n; ++i){
int now = i;
for(int j = 20; ~j; --j)
if(to[now][j] > i/2) now = to[now][j];
now = to[now][0];
res = res*(dep[now]+1)%p;
}
printf("%lld\n", res);
return 0;
}
int T;
int main(){
scanf("%d", &T);
while(T--) _init(), _main();
return 0;
}
UOJ #6. 【NOI2014】随机数生成器
AC Time:2026-04-17 19:35:27
发现肯定会选当前可选范围内最小的数,于是直接模拟即可。
记得卡空间。
#include <bits/stdc++.h>
#define llong long long
#define N 5005
using namespace std;
#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
x = 0; int w = 1;
char ch = gc();
while(ch < '0' || ch > '9'){
if(ch == '-') w = -w;
ch = gc();
}
while(ch >= '0' && ch <= '9')
x = (x<<3)+(x<<1)+(ch^48), ch = gc();
x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
return read(x), read(y...);
}
int a2[N*N];
int n, m, q, a, b, c, d;
llong x;
short b1[N*N], b2[N*N];
int ans[N*2];
bitset<N> vis[N];
int main(){
read(x, a, b, c, d);
read(n, m, q);
for(int i = 1; i <= n*m; ++i) a2[i] = i;
for(int i = 1; i <= n*m; ++i){
x = (a*x%d*x%d+b*x%d+c)%d;
swap(a2[i], a2[x%i+1]);
}
while(q--){
int x, y; read(x, y);
swap(a2[x], a2[y]);
}
for(int i = 1, k = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j, ++k)
b1[a2[k]] = i, b2[a2[k]] = j;
for(int i = 0; i <= n+1; ++i) vis[i][0] = vis[i][m+1] = true;
for(int i = 0; i <= m+1; ++i) vis[0][i] = vis[n+1][i] = true;
for(int i = 1, j = 0; i <= n*m && j <= n+m-1; ++i){
if(vis[b1[i]][b2[i]]) continue;
int x = b1[i], y = b2[i];
ans[++j] = a2[(x-1)*m+y];
int x1 = x+1, x2 = x-1, y1 = y-1, y2 = y+1;
while(!vis[x1][y-1]) ++x1;
while(!vis[x2][y+1]) --x2;
while(!vis[x+1][y1]) --y1;
while(!vis[x-1][y2]) ++y2;
for(int xx = x+1; xx < x1; ++xx)
for(int yy = y-1; yy > y1; --yy)
vis[xx][yy] = true;
for(int xx = x-1; xx > x2; --xx)
for(int yy = y+1; yy < y2; ++yy)
vis[xx][yy] = true;
}
for(int i = 1; i <= n+m-1; ++i)
printf("%d ", ans[i]);
return 0;
}
UOJ #7. 【NOI2014】购票
AC Time:2026-04-21 21:21:35
发现我们需要查链上的 \(\min f_{p_i}\),链的其中一个端点为 \(1\)。我们可以使用树剖套李超树,但是 \(\mathrm O(n \log^3 n)\),过个鬼的 \(n \le 2 \times 10^5\)。
查看题解发现一个 trick:先 DFS 一遍制造一个出栈序 \(\text{idx}_i\)(如果你不知道什么是出栈序,参见代码中的 dfs1 函数),然后再 DFS 一遍,那么 dfs 到 \(u\) 时,对于点 \(u, v\),其中 \(v\) 是 \(u\) 的祖先,\([\text{idx}_u, \text{idx}_v]\) 的点要么在链 \(u - v\) 上,要么没有被预处理。
然后我们只需要使用线段树套李超树即可,复杂度 \(\mathrm O(n \log^2 n)\)。
#include <bits/stdc++.h>
#define llong long long
#define N 200005
using namespace std;
#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
x = 0; int w = 1;
char ch = gc();
while(ch < '0' || ch > '9'){
if(ch == '-') w = -w;
ch = gc();
}
while(ch >= '0' && ch <= '9')
x = (x<<3)+(x<<1)+(ch^48), ch = gc();
x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
return read(x), read(y...);
}
int n, tid;
vector<int> G[N];
llong l[N], p[N], q[N];
llong dep[N], dp[N];
int fa[N][21], idx[N], idcnt;
int tmp[N], m;
namespace LiChaoSegT{
struct Seg{llong k, b; bool vis;};
#define get(s,x) (s.vis ? s.k*x+s.b : (llong)1e18+3)
Seg val[N<<6];
int ls[N<<6], rs[N<<6], tsiz;
#define mid ((l+r)>>1)
class LiChaoTree{
int root;
inline void insert(Seg k1, int &x, int l = 1, int r = m){
if(!x) x = ++tsiz;
if(!val[x].vis){val[x] = k1; return;}
Seg k2 = val[x];
if(get(k1, tmp[mid]) < get(k2, tmp[mid])) swap(k1, k2);
val[x] = k2;
if(get(k1, tmp[l]) < get(k2, tmp[l])) insert(k1, ls[x], l, mid );
if(get(k1, tmp[r]) < get(k2, tmp[r])) insert(k1, rs[x], mid+1, r);
return;
}
inline llong getmin(int pos, int &x, int l = 1, int r = m){
if(!x) return (llong)1e18+3;
if(l == r) return get(val[x], tmp[pos]);
if(pos <= mid) return min(get(val[x], tmp[pos]), getmin(pos, ls[x], l, mid ));
else return min(get(val[x], tmp[pos]), getmin(pos, rs[x], mid+1, r));
}
public:
inline void insert(Seg k1){insert(k1, root);};
inline llong getmin(int pos){return getmin(pos, root);}
};
LiChaoTree root[N<<2];
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
inline void insert(int pos, Seg k, int x = 1, int l = 1, int r = n){
root[x].insert(k);
if(l == r) return;
if(pos <= mid) insert(pos, k, ls(x), l, mid );
else insert(pos, k, rs(x), mid+1, r);
}
inline llong getmin(int L, int R, int pos, int x = 1, int l = 1, int r = n){
if(L <= l && R >= r) return root[x].getmin(pos);
if(R <= mid) return getmin(L, R, pos, ls(x), l, mid );
if(L > mid) return getmin(L, R, pos, rs(x), mid+1, r);
return min(getmin(L, R, pos, ls(x), l, mid), getmin(L, R, pos, rs(x), mid+1, r));
}
}
using LiChaoSegT::Seg;
using LiChaoSegT::getmin;
using LiChaoSegT::insert;
inline void dfs1(int u){
for(int v : G[u]) dfs1(v);
idx[u] = ++idcnt;
return;
}
inline void dfs2(int u){
if(u != 1){
int v = u;
for(int i = 20; ~i; --i)
if(dep[u]-dep[fa[v][i]] <= l[u]) v = fa[v][i];
dp[u] = getmin(idx[u], idx[v], lower_bound(tmp+1, tmp+m+1, p[u])-tmp)+(dep[u]*p[u]+q[u]);
insert(idx[u], {-dep[u], dp[u], true});
}
else insert(n, {0, 0, true});
for(int v : G[u]) dfs2(v);
return;
}
int main(){
read(n, tid);
for(int i = 0; i <= 20; ++i) fa[1][i] = 1;
for(int i = 2; i <= n; ++i){
read(fa[i][0], dep[i], p[i], q[i], l[i]);
dep[i] += dep[fa[i][0]];
for(int j = 1; j <= 20; ++j)
fa[i][j] = fa[fa[i][j-1]][j-1];
G[fa[i][0]].push_back(i);
tmp[i] = p[i];
}
sort(tmp+1, tmp+n+1), m = unique(tmp+1, tmp+n+1)-tmp-1;
dfs1(1), dfs2(1);
for(int i = 2; i <= n; ++i) printf("%lld\n", dp[i]);
return 0;
}
UOJ #8. Quine
AC Time:2026-04-21 21:49:40
Quine. 没什么好说的。
#include <stdio.h>
int main(){
char s[] = "#include <stdio.h>%cint main(){%c char s[] = %c%s%c;%c printf(s, 10, 10, 34, s, 34, 10, 10, 10);%c}%c";
printf(s, 10, 10, 34, s, 34, 10, 10, 10);
}
UOJ #9. 【UTR #1】vfk的数据
AC Time:2026-04-21 22:19:31
发现题目就是一个高精度数比较,直接用 string 存一下数,sort 一下就行了。
#include <bits/stdc++.h>
#define llong long long
#define N 100005
using namespace std;
string a[N];
#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
x = 0; int w = 1;
char ch = gc();
while(ch < '0' || ch > '9'){
if(ch == '-') w = -w;
ch = gc();
}
while(ch >= '0' && ch <= '9')
x = (x<<3)+(x<<1)+(ch^48), ch = gc();
x *= w;
}
inline void read(char* x){
*x = gc();
while(*x == ' ' || *x == '\r' || *x == '\n') *x = gc();
while(*x < '0' || *x > '9') *++x = gc();
*x = '\0', --p1;
}
inline void read(string& x){
char ch = gc();
while(ch < '0' || ch > '9') ch = gc();
while(ch >= '0' && ch <= '9')
x += ch, ch = gc();
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
return read(x), read(y...);
}
int n;
char s[N];
int main(){
read(n, s);
for(int i = 1; i <= n; ++i) read(a[i]);
sort(a+1, a+n+1, [&](string o1, string o2){return o1.size()==o2.size() ? o1<o2 : o1.size()<o2.size();});
for(int i = 1; i <= n; ++i)
cout << s << a[i] << ".in\n";
return 0;
}
UOJ #10. 【UTR #1】pyx的难题
AC Time:2026-04-22 21:50:57
发现赋给特殊题目的权值越高完成就越快,我们可以直接二分答案。
\(\mathrm O(n \log^2 n)\),不知道为什么过 \(3 \times 10^5\) 需要大力卡常。
#include <bits/stdc++.h>
#define llong long long
#define N 300005
using namespace std;
#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
x = 0; int w = 1;
char ch = gc();
while(ch < '0' || ch > '9'){
if(ch == '-') w = -w;
ch = gc();
}
while(ch >= '0' && ch <= '9')
x = (x<<3)+(x<<1)+(ch^48), ch = gc();
x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
return read(x), read(y...);
}
int n, m, sp; llong T, k;
struct Node{
llong t;
mutable llong s;
int p, id;
} a[N];
llong ans[N];
llong tmp[N], ark[N];
__always_inline bool operator<(const Node& o1, const Node& o2){return o1.p<o2.p;}
__always_inline bool operator>(const Node& o1, const Node& o2){return o1.p>o2.p;}
__always_inline bool operator<=(const Node& o1, const Node& o2){return o1.p<=o2.p;}
__always_inline bool operator>=(const Node& o1, const Node& o2){return o1.p>=o2.p;}
Node heap[N]; int top;
__always_inline void adjust(int x){
for(; x != 1; x >>= 1){
if(heap[x].p > heap[x>>1].p) swap(heap[x], heap[x>>1]);
else break;
}
return;
}
__always_inline void pop(){
if(top == 1) return top = 0, void();
int x = 1;
heap[1] = heap[top--];
while((x<<1) <= top){
if((x<<1|1) > top){
if(heap[x] < heap[x<<1]) swap(heap[x], heap[x<<1]);
break;
}
if(heap[x<<1] >= heap[x<<1|1] && heap[x<<1] > heap[x]) swap(heap[x], heap[x<<1]), x = x<<1;
else if(heap[x<<1|1] >= heap[x<<1] && heap[x<<1|1] > heap[x]) swap(heap[x], heap[x<<1|1]), x = x<<1|1;
else break;
}
return;
}
__always_inline int check(int k){
a[sp].p = k;
top = 0;
for(int i = 1; i <= n; ++i){
heap[++top] = a[i], adjust(top);
llong t = a[i+1].t-a[i].t;
while(top && t){
if(t >= heap[1].s){
t -= heap[1].s;
if(a[i+1].t-t > T) return -1;
else if(heap[1].id == a[sp].id) return a[i+1].t-t < T;
pop();
}
else heap[1].s -= t, t = 0;
}
}
assert(false);
return false;
}
int main(){
read(n);
for(int i = 1; i <= n; ++i){
read(a[i].t, a[i].s, a[i].p);
tmp[i-1] = a[i].p;
a[i].id = i;
}
a[n+1] = {(llong)1e18+3, 0, 0, 0};
read(T);
sort(a+1, a+n+1, [&](Node o1, Node o2){return o1.t<o2.t;});
for(int i = 1; i <= n; ++i)
if(a[i].p == -1) sp = i;
tmp[n] = 0;
sort(tmp, tmp+n+1);
for(int i = 1; i <= n; ++i)
if(tmp[i]+1 != tmp[i+1]) ark[++m] = tmp[i]+1;
int l = 1, r = m;
while(l < r){
int mid = (l+r)>>1;
int op = check(ark[mid]);
if(op == 0){
l = r = mid;
break;
}
if(op == -1) l = mid+1;
else r = mid-1;
}
a[sp].p = ark[l];
top = 0;
for(int i = 1; i <= n; ++i){
heap[++top] = a[i], adjust(top);
llong t = a[i+1].t-a[i].t;
while(top && t){
if(t >= heap[1].s){
t -= heap[1].s;
ans[heap[1].id] = a[i+1].t-t;
pop();
}
else heap[1].s -= t, t = 0;
}
}
printf("%lld\n", ark[l]);
for(int i = 1; i <= n; ++i) printf("%lld ", ans[i]);
return 0;
}
UOJ #11. 【UTR #1】ydc的大树
AC Time:2026-04-23 20:44:26
好玩的分讨题,让我 1d 就做了一个题。
我们发现最远黑点必定是黑直径的端点,我们考虑这些直径。
我们考虑树的中心,以下称“侧”为以树的中心为根在哪个子树里,那么发现一个点的最远点必定和它在不同侧。
发现中心可以是点或者边,于是分讨以下即可。
细节不想讲了看代码吧,这题真的给我神秘到了。
#include <bits/stdc++.h>
#define llong long long
#define N 100005
using namespace std;
#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
x = 0; int w = 1;
char ch = gc();
while(ch < '0' || ch > '9'){
if(ch == '-') w = -w;
ch = gc();
}
while(ch >= '0' && ch <= '9')
x = (x<<3)+(x<<1)+(ch^48), ch = gc();
x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
return read(x), read(y...);
}
int n, m;
int col[N];
vector<pair<int, int>> G[N];
int a[N], b[N], siz[N], tsiz[N], dep[N], ans[N], pcnt;
inline pair<int, int> dfs1(int u, int fa = 0, int dis = 0){
pair<int, int> res;
if(col[u]) res = make_pair(dis, u);
else res = make_pair(-1e9-7, -1e9-7);
for(auto tmp : G[u]){
int v = tmp.first, w = tmp.second;
if(v == fa) continue;
res = max(res, dfs1(v, u, dis+w));
}
return res;
}
inline bool dfs2(int u, int fa, int dest, int dist){
if(u == dest) return true;
for(auto tmp : G[u]){
int v = tmp.first, w = tmp.second;
if(v == fa) continue;
if(!dfs2(v, u, dest, dist-w)) continue;
++pcnt, a[pcnt] = u, b[pcnt] = dist;
return true;
}
return false;
}
inline void dfs3(int u, int fa, int tar, int dis = 0){
siz[u] = col[u];
dep[u] = col[u] ? 0 : -1e9-7;
tsiz[u] = (dis==tar)&&col[u];
for(auto tmp : G[u]){
int v = tmp.first, w = tmp.second;
if(v == fa) continue;
dfs3(v, u, tar, dis+w);
dep[u] = max(dep[u], dep[v]+w);
siz[u] += siz[v], tsiz[u] += tsiz[v];
}
return;
}
inline void dfs4(int u, int fa, int ss, int delta){
if(!siz[u]) return;
if(!col[u]) ans[u] = siz[u]+(tsiz[u]==ss)*delta;
for(auto tmp : G[u]){
int v = tmp.first;
if(v == fa) continue;
dfs4(v, u, ss, delta);
}
return;
}
int main(){
read(n, m);
for(int i = 1, x; i <= m; ++i)
read(x), col[x] = true, ans[x] = -1;
for(int i = 1; i < n; ++i){
int u, v, w; read(u, v, w);
G[u].emplace_back(v, w);
G[v].emplace_back(u, w);
}
int u, v, w;
u = dfs1(1).second;
tie(w, v) = dfs1(u);
a[++pcnt] = u;
dfs2(v, 0, u, w);
int mid = 1;
while(b[mid]*2 < w) ++mid;
if(b[mid]*2 == w){
int d = b[mid], cnt = 0, sid = col[a[mid]];
mid = a[mid];
if(!col[mid]) ans[mid] = m;
dfs3(mid, 0, d);
for(auto now : G[mid]){
if(dep[now.first] == d-now.second) ++cnt;
else sid += siz[now.first];
}
for(auto now : G[mid]){
int u = now.first;
dfs4(u, mid, tsiz[u], ((cnt==2)&&(dep[now.first] == d-now.second)) ? (m-siz[u]-sid) : 0);
}
}
else{
int d1 = b[mid-1], d2 = w-b[mid];
int mid1 = a[mid-1], mid2 = a[mid];
dfs3(mid1, mid2, d1), dfs3(mid2, mid1, d2);
dfs4(mid1, mid2, tsiz[mid1], m-siz[mid1]);
dfs4(mid2, mid1, tsiz[mid2], m-siz[mid2]);
}
sort(ans+1, ans+n+1, greater<int>());
int cnt = 1;
while(ans[cnt] == ans[1]) ++cnt;
printf("%d %d", ans[1], cnt-1);
return 0;
}
UOJ #12. 【UER #1】猜数
AC Time:2026-04-23 21:11:03
好水的题。
因为 \(ab = gl = n\),设 \(a = gk_1, b = gk_2\),那么 \(l = gk_1k_2\)。问题转化为给定 \(k_1k_2\),求 \(k_1 + k_2\) 的最值,保证 \(k_1k_2\) 为完全平方数。
然后就是小学数学题了。
#include <bits/stdc++.h>
#define llong long long
using namespace std;
llong a, b;
int _main(){
cin >> a >> b;
cout << a*(llong)sqrt(b/a)*2 << " " << a+b << endl;
return 0;
}
int T;
int main(){
cin >> T;
while(T--) _main();
return 0;
}

浙公网安备 33010602011771号