Codeforces Round #628
比赛链接 https://codeforces.com/contest/1325
比赛记录 https://blog.csdn.net/cheng__yu_/article/details/105395197
C. Ehab and Path-etic MEXs
思路:防止 0、1、2放在同一条链上
考虑:
m
e
x
≥
1
mex\ge 1
mex≥1 、
m
e
x
≥
2
mex\ge 2
mex≥2 、
m
e
x
≥
3
mex\ge 3
mex≥3的情况
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10,inf=1e9;
int n;
vector<pair<int,int> > G[maxn];
int label[maxn];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n-1;++i)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back({v,i});
G[v].push_back({u,i});
}
memset(label,-1,sizeof(label));
for(int i=1;i<=n;++i)
{
if(G[i].size()>=3)
{
for(int j=0;j<=2;++j)
label[G[i][j].second]=j;
int cnt=2;
for(int j=1;j<=n-1;++j)
if(label[j]==-1)
label[j]=++cnt;
for(int j=1;j<=n-1;++j)
cout<<label[j]<<"\n";
return 0;
}
}
for(int i=1;i<=n-1;++i)
cout<<i-1<<"\n";
return 0;
}
D. Ehab the Xorcist
题意:构造一个数组,使得和为v,异或和为 u
思路:
- u、v的奇偶性相同:因为 a + b = a a+b=a a+b=a ^ b + 2 ( a & b ) b+2(a\&b) b+2(a&b),奇偶性不变
- u大于v时无解,异或是不进位加法,不可以大于加法
- u==v时,答案为 u
- 最长长度为 3 : 因为存在 u 、 v − u 2 \frac{v-u}2 2v−u、 v − u 2 \frac{v-u}2 2v−u
- 考虑长度为2的情况,即构造 a 和 b。由于
a
+
b
=
a
a+b=a
a+b=a ^
b
+
2
(
a
&
b
)
b+2(a\&b)
b+2(a&b),得到
(
a
&
b
)
=
v
−
u
2
(a\&b)=\frac{v-u}2
(a&b)=2v−u
&运算相当于取公共位,而 ^ 相当于不要公共位。 - 那么就取 ( a & b ) = v − u 2 = b (a\&b)=\frac{v-u}2=b (a&b)=2v−u=b,即 b b b 取公共位,取: a = u − b a=u-b a=u−b,判断一下, a a a ^ b = = u b==u b==u即可
- 因为在 a 里面包含了 非公共位和公共位,这些位可能会产生进位,所以需要判断
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10,inf=1e9;
int main()
{
ll u,v;
cin>>u>>v;
if(u>v||(u-v&1))
{
puts("-1");
return 0;
}
if(u==v&&v==0)
{
printf("%lld\n",u);
return 0;
}
if(u==v)
{
puts("1");
printf("%lld\n",u);
return 0;
}
ll a=(v-u)/2;
ll b=v-a;
if((a^b)==u)
{
puts("2");
printf("%lld %lld\n",a,b);
}
else
{
puts("3");
printf("%lld %lld %lld\n",u,a,a);
}
return 0;
}
E. Ehab’s REAL Number Theory Problem
题意:在数组a ,找最小的子序列,使得子序列每一项的乘积为平方数。输出最小的长度,每个元素的素因子不超过7个
思路:每一个元素最多两个素因子。这样,就只剩下 1、p、pq 这样的数,每个素因子看成一个点,对它们进行连边。最后如果找到一个环,就一定是一个平方数,找一个最小的环。因为数据为1e6,所以可以在[1,1000]内枚举起点
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+10,inf=0x7f7f7f7f;
int n,a[maxn];
const int N=10000;
int pcnt,prime[N+10],visit[N+10];
void init()
{
pcnt=0;
for(int i=2;i<=N;++i)
{
if(!visit[i]) prime[++pcnt]=i;
for(int j=1;j<=pcnt&&i*prime[j]<=N;++j)
{
visit[i*prime[j]]=1;
if(i%prime[j]==0)
break;
}
}
}
int head[maxn],cnt;
struct Edge
{
int to,nxt;
}edges[maxn<<1];
void add(int u,int v)
{
edges[++cnt].to=v;
edges[cnt].nxt=head[u];
head[u]=cnt;
}
void solve(int n)
{
if(n==1)
{
add(1,1),add(1,1);
return;
}
vector<int> p;
for(int i=1;prime[i]*prime[i]<=n;++i)
{
if(n%prime[i]==0)
{
int res=0;
while(n%prime[i]==0)
n/=prime[i],res++;
if(res&1)
p.push_back(prime[i]);
else
p.push_back(1);
}
}
if(n>1)
p.push_back(n);
if(p.size()==1)
add(1,p[0]),add(p[0],1);
else if(p.size()==2)
add(p[0],p[1]),add(p[1],p[0]);
}
int depth[maxn],fa[maxn];
int ans=inf;
int bfs(int s)
{
memset(depth,inf,sizeof(depth));
memset(fa,-1,sizeof(fa));
queue<int> q;
q.push(s);
depth[s]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=edges[i].nxt)
{
int v=edges[i].to;
if(v==fa[u])
continue;
if(depth[v]==inf)
{
depth[v]=depth[u]+1;
q.push(v);
fa[v]=u;
}
else
ans=min(ans,depth[v]+depth[u]+1);
}
}
return inf;
}
int main()
{
init();
memset(head,-1,sizeof(head)),cnt=-1;
cin>>n;
for(int i=1;i<=n;++i)
cin>>a[i],solve(a[i]);
for(int i=1;i<=1000;++i)
if(!visit[i])
bfs(i);
if(ans==inf) puts("-1");
else printf("%d\n",ans);
return 0;
}