发现今天做不了一点题,遂来补以前的比赛。
B. 378QAQ and Mocha's Array
秒了。排序,取最小的数记为 \(x\),再取 最小的无法被 \(x\) 整除的数记为 \(y\),如果仍然存在无法被 \(y\) 整除的数,则无解。
C. Chamo and Mocha's Array
容易想到一个结论:如果一个数比它左边或右边的数小,那么它可以成为答案。但这样是不对的,样例:3 1 4 1 5。
正确结论:如果一个数向左右扩展两格后有比它大的数,那么它可以成为答案。
D. Paint the Tree
首先我们找到 \(a,b\) 点间靠近 \(a\) 的中点,以这个点作为根 \(root\),然后答案就是 \(\mathbf{2}*(n-\mathbf{1})+dis-dist\),\(dis\) 是 \(b\) 到 \(root\) 的距离,\(dist\) 是以 \(root\) 为根时的最大深度。
实际上很简单,只不过我赛时降智,一直在想走重儿子而不走最深的儿子,还坑了xht呜呜呜。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2*114514,M=1919810;
struct xx{
ll next,to;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y){
e[++cnt].next=head[x];
e[cnt].to=y;
head[x]=cnt;
}
ll T;
ll n,m,k,x,a,b,rt;
ll siz[N],dis[N],son[N];
void dfs(ll u,ll fa){
siz[u]=1,son[u]=0;
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(v==fa) continue;
dis[v]=dis[u]+1;
dfs(v,u);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v]) son[u]=v;
}
}
void getrt(ll u,ll tot){
if(tot==0){
rt=u;
return;
}
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(dis[v]>dis[u]) continue;
getrt(v,tot-1);
}
}
void solve(){
cin>>n;
cin>>a>>b;
cnt=0;
for(int i=1;i<n;++i){
ll x,y;
cin>>x>>y;
add(x,y),add(y,x);
}
dis[a]=0,dfs(a,0);
ll di=dis[b]-dis[a]; di=(di+1)/2;
ll res=di,ans=0;
getrt(b,di); //向上走di条边,取到靠a的中点
dis[rt]=0,dfs(rt,0);
for(int i=1;i<=n;++i) ans=max(ans,dis[i]);
cout<<2*(n-1)-ans+res<<'\n';
for(int i=1;i<=cnt;++i) head[i]=0;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>T;
while(T--) solve();
return 0;
}