Codeforces Round #628 (Div. 2)

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值