C. Ehab and Path-etic MEXs
You are given a tree consisting of n nodes. You want to write some labels on the tree’s edges such that the following conditions hold:
Every label is an integer between 0 and n−2 inclusive.
All the written labels are distinct.
The largest value among MEX(u,v) over all pairs of nodes (u,v) is as small as possible.
Here, MEX(u,v) denotes the smallest non-negative integer that isn’t written on any edge on the unique simple path from node u to node v.
Input
The first line contains the integer n (2≤n≤105) — the number of nodes in the tree.
Each of the next n−1 lines contains two space-separated integers u and v (1≤u,v≤n) that mean there’s an edge between nodes u and v. It’s guaranteed that the given graph is a tree.
Output
Output n−1 integers. The ith of them will be the number written on the ith edge (in the input order).
Examples
inputCopy
3
1 2
1 3
outputCopy
0
1
inputCopy
6
1 2
1 3
2 4
2 5
5 6
outputCopy
0
3
2
4
1
题意:给定一棵 n 个点的树,你可以对树边标号为 0,1,2,…,n−2 。定义 MEX(u,v) 是说点 u 到 v 的路径上最小的未出现的标号(例如路径上的标号是 0,2,3 , 那结果就是 1 ),给出一种构造方案使得对于所有 MEX(u,v) 的最大值最小。
分析:如果至少有一个点的度数 ≥3 (即不为链),那么我们就能把 0,1,2 这三个数字分配到该点的三条邻边上,这样就能保证我任选一条路径不能同时存在这三个最小的数。
#include <bits/stdc++.h>
#define MAX_INT ((unsigned)(-1)>>1)
#define MIN_INT (~MAX_INT)
#define db printf("where!\n");
using namespace std;
#define ll long long
int read()
{
int c=0;int flag=1;
char s;
while((s=getchar())>'9'||s<'0')if(s=='-')flag=-1;
c=s-'0';
while((s=getchar())<='9'&&s>='0') c=c*10+s-'0';
return c*flag;
}
const int maxn=1e5+5;
struct node
{
int u,v,va;
}a[maxn];
int du[maxn];
int temp=0;
int main(void)
{
int n;cin>>n;
for(int i=0;i<n-1;i++){
cin>>a[i].u>>a[i].v;
du[a[i].u]++;
du[a[i].v]++;
if(du[a[i].u]>2) temp=a[i].u;
if(du[a[i].v]>2) temp=a[i].v;
}
int res=3,tem=0;
if(temp==0) res=0;
for(int i=0;i<n-1;i++){
if((a[i].u==temp||a[i].v==temp)&&tem<3){
cout<<tem<<endl;
tem++;
}
else{
cout<< res++ <<endl;
}
}
return 0;
}
D. Ehab the Xorcist
Given 2 integers u and v, find the shortest array such that bitwise-xor of its elements is u, and the sum of its elements is v.
Input
The only line contains 2 integers u and v (0≤u,v≤1018).
Output
If there’s no array that satisfies the condition, print “-1”. Otherwise:
The first line should contain one integer, n, representing the length of the desired array. The next line should contain n positive integers, the array itself. If there are multiple possible answers, print any.
Examples
inputCopy
2 4
outputCopy
2
3 1
inputCopy
1 3
outputCopy
3
1 1 1
inputCopy
8 5
outputCopy
-1
inputCopy
0 0
outputCopy
0
Note
In the first sample, 3⊕1=2 and 3+1=4. There is no valid array of smaller length.
Notice that in the fourth sample the array is empty.
题意:给定两个数字 u 和 v ,构造一个最短的数列 an 满足 a1⊕a2⊕…⊕an=u 并且 ∑ ai=v 。
分析:首先考虑不能构造的情况,容易发现 u>v 是不能构造的,然后根据奇偶性可以发现 v−u 为奇数时不能构造。在排除了本题的一些特判,比如 u=v=0 ,u=v 之后,本题就转化为 v−u 为偶数时的构造问题。由于 v−u 为偶数,我们很快就能给出构造的上界是 3 ,因为 (v - u) / 2 ^ (v - u) / 2 ^ u = u 。但是还要特判一下能否构造长度为 2 的数列,即 (v - u) / 2 ^ ((v - u) / 2 ^ u) = u 。
#include <bits/stdc++.h>
#define MAX_INT ((unsigned)(-1)>>1)
#define MIN_INT (~MAX_INT)
#define db printf("where!\n");
using namespace std;
#define ll long long
int read()
{
int c=0;int flag=1;
char s;
while((s=getchar())>'9'||s<'0')if(s=='-')flag=-1;
c=s-'0';
while((s=getchar())<='9'&&s>='0') c=c*10+s-'0';
return c*flag;
}
const int maxn=1e5+5;
int main(void)
{
ll a,b;
cin>>a>>b;
if(a==0&&b==0) cout<<0<<endl;
else if(a==b) printf("1\n%lld\n",a);
else if(a>b||a&1 ^ b&1) cout<<-1<<endl;
else{
ll t=(b-a)/2;
if(!(t&a)) cout<<2<<endl<<a+t<<" "<<t<<endl;
else cout<<3<<endl<<a<<" "<<t<<" "<<t<<endl;
}
return 0;
}
E. Ehab’s REAL Number Theory Problem
You are given an array a of length n that has a special condition: every element in this array has at most 7 divisors. Find the length of the shortest non-empty subsequence of this array product of whose elements is a perfect square.
A sequence a is a subsequence of an array b if a can be obtained from b by deletion of several (possibly, zero or all) elements.
Input
The first line contains an integer n (1≤n≤105) — the length of a.
The second line contains n integers a1, a2, …, an (1≤ai≤106) — the elements of the array a.
Output
Output the length of the shortest non-empty subsequence of a product of whose elements is a perfect square. If there are several shortest subsequences, you can find any of them. If there’s no such subsequence, print “-1”.
Examples
inputCopy
3
1 4 6
outputCopy
1
inputCopy
4
2 3 6 6
outputCopy
2
inputCopy
3
6 15 10
outputCopy
3
inputCopy
4
2 3 5 7
outputCopy
-1
Note
In the first sample, you can choose a subsequence [1].
In the second sample, you can choose a subsequence [6,6].
In the third sample, you can choose a subsequence [6,15,10].
In the fourth sample, there is no such subsequence.
题意:给定一个数组 an ,数组中任意一个元素的因子数不超过 7 ,找出一个最短的子序列,满足该子序列之积为完全平方数。
分析:由于任意元素因子数不超过 7 ,因此 ai 的质因子数 ≤2 (如果质因子数为 3 将有 8 个因子)。因此我们先将所有给定元素进行预处理,去除所有平方因子(假设一个元素为 22⋅3 那它等价于 3 ),然后所有元素只能是 1,p,pq 中的一种形式( p,q 为质数)。完成预处理后不难发现,如果存在 1 ,那么结果就是最短子序列长度就是 1 ;如果存在两个相同元素,那么结果就是 2 。
然后,我们就可以按照处理后的元素建图了,假设一个元素是 pq ,那么在 p 和 q 之间建一条边;假设一个元素是 p 那么在 p 和 1 之间建边;本题的答案就是该图上的最小环,因为每个点都会被两条边连接,说明每个点被选中了偶数次。由于边权全部为 1 ,直接跑 bfs 即可,但是如果对每个节点搜索,复杂度是 O(NM) 的,本题中我们只需要对所有权值 <= √ max ai 的节点搜索,因为权值 > √ max ai 的节点只可能出现 1 次,必定为奇数不能成环。
#include <bits/stdc++.h>
#define MAX_INT ((unsigned)(-1)>>1)
#define MIN_INT (~MAX_INT)
#define db printf("where!\n");
using namespace std;
#define ll long long
int read()
{
int c=0;int flag=1;
char s;
while((s=getchar())>'9'||s<'0')if(s=='-')flag=-1;
c=s-'0';
while((s=getchar())<='9'&&s>='0') c=c*10+s-'0';
return c*flag;
}
const int maxn=1e6+5;
int n, ans = 2e9;
vector<int> a, fac;
vector<int> vec[maxn];
int dis[maxn];
bool vis[maxn];
int init(int x)
{
for(int i=2;i*i<=x;i++){
if(x%i) continue;
int cnt=0;
while(x%i==0) x/=i,cnt++;
if(cnt&1) x*=i;
}
return x;
}
void bfs(int x)
{
for(int i:fac) dis[i]=2e9,vis[i]=0;
dis[x]=0;
queue<int> q;
q.push(x);
vis[x]=1;
while(!q.empty()){
int top=q.front();
q.pop();
vis[top]=0;
for(int i:vec[top]){
if(dis[i]>dis[top]+1){
dis[i]=dis[top]+1;
q.push(i);
vis[i]=1;
}
else if(vis[i]) ans=min(ans,dis[i]+dis[top]+1);
}
}
}
int main(void)
{
cin>>n;
a.resize(n);
for(int i=0;i<n;i++){
cin>>a[i];
a[i]=init(a[i]);
}
sort(a.begin(),a.end());
if(a[0]==1){cout<<1;return 0;}
a.erase(unique(a.begin(),a.end()),a.end());
if(a.size()<n){cout<<2;return 0;}
for(int i:a){
vector<int> tmp(2,-1);
tmp[0]=i;
for(int j=2;j*j<=i;j++){//将i进行分解成两个质数i和j
if(i%j) continue;
tmp[0]=j;
i/=j;
if(i!=1) tmp[1]=i;
break;
}
if(tmp[1]==-1) tmp[1]=1;
fac.push_back(tmp[0]),fac.push_back(tmp[1]);//建图
vec[tmp[1]].push_back(tmp[0]);
vec[tmp[0]].push_back(tmp[1]);
}
sort(fac.begin(),fac.end());
fac.erase(unique(fac.begin(),fac.end()),fac.end());
for(int i=1;i<=1000;i++){
if(vec[i].empty()) continue;
bfs(i);
}
if(ans==2e9) cout<<-1;
else cout<<ans;
return 0;
}