Codeforces Round #628 (Div. 2)

耻辱场,必铭记

A   a,b只要输出1  x-1就是lcm(a,b)+gcd(a,b)=x了

B  记录数组放到set里,答案set.size

C 只要把他的叶子结点连接的那几条线变成最小的距离即可,但有一个特殊样例

2

1 2

0

因为我是用出现次数是1的就是叶子结点,所有我wa在19,赛后冷静下来思考了一波,觉得自己是真的比赛的时候不相信自己

细节也不注意。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define pii pair<int,int>
#define mak(n,m) make_pair(n,m)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 998244353
const int maxn=1e5+10;
int n;
int u,v,ans[maxn],vis[maxn],pos[maxn];
int main(){
    mem(ans,-1);
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        vis[u]++;vis[v]++;pos[u]=i;pos[v]=i;
    }
    int t=0;
    for(it i=1;i<=n;i++){
        if(vis[i]==1){
            ans[pos[i]]=t++;
        }
    }
    for(it i=n-1;i>=1;i--){
        if(ans[i]==-1){
            ans[i]=t++;
        }
    }
    for(it i=1;i<n;i++){
        if(ans[i]==n-1){ans[i]=0;}
        printf("%d\n",ans[i]);
    }
    return 0;
}

 

D

题意:

x,y

求最少的数组个素和其元素,元素异或和为x,元素累加为y

我的思路:

x把他变为二进制,存一个数组a,

用另外一个数组b进行模拟,,把答案存在c这个数组,从0开始往上

首先,b0=y,(y-a0)%2==1 输入-1,然后y-=a0,如果a0是1,那么zhi+=1<<0,b1=y/2。

到b1这层,如果a1是1,那么zhi+=1<<a1,b1-=a1,b1%2==1 那么进行b1减一,b0现在等于2,查看(zhi>>(1))&1,如果是1 ,就去查看数组c里面(ci>>(1))==0,ci+=1<<(1),如果凑不足两个,就c数组中添入1<<(i-1),如果b1==0 a1==1这种情况输出-1,以此类推循环64次足够了

是不是很麻烦,比赛的时候写了这种,写完发现比赛快结束了,交了几分,都错了,然后发现1 1我输出-1,然后赛后检查发现少些了一个else,然后就ac了

 

#include<iostream>
#include<map>
#include<set>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define ull unsigned long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define pii pair<int,int>
#define mak(n,m) make_pair(n,m)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 998244353
const int maxn=1e5+10;
ll n,m;
ll a[110],b[110],da[maxn];
int main(){
    scanf("%lld%lld",&n,&m);
    if(n==0){
        if(m==0){printf("0\n");return 0;}
        else if(m&1){
           printf("-1\n");return 0;
        }
        else{
            printf("2\n");
            printf("%lld %lld",m/2,m/2);return 0;
        }
    }
    ll ans=n,sum=m;
    int c=0,cc=0;
    while(ans){
        a[c++]=ans%2;
        ans/=2;
    }
    int f=0,p=0;
    ll daa=0;
    b[0]=m;
    for(it i=0;i<=100;i++){
        if(a[i] && b[i]){
            b[i]--;daa+=(ll)1<<i;
        }
        else if(a[i] && !b[i]){f=1;break;}//就是这里少了个else,淦
        if(b[i]%2==1){
            if(i==0){f=1;break;}
            int ff=2;
            if(!((daa>>(i-1))&1)){
                daa+=((ll)1<<(i-1));ff--;
            }
            for(it j=0;j<p;j++){
                if((da[j]>>(i-1))&1){continue;}
                if(ff){
                    da[j]+=(ll)1<<(i-1);ff--;
                }
            }
            for(it j=0;j<ff;j++){
                da[p++]=(ll)1<<(i-1);
            }
            b[i]--;
        }
        b[i+1]+=b[i]/2;
    }
    if(f){printf("-1\n");return 0;}
    da[p++]=daa;
    printf("%d\n",p);
    for(it i=0;i<p;i++){
        printf(i==p-1?"%lld\n":"%lld ",da[i]);
    }
    return 0;
}

 

 

至于为什么说我的思路呢,因为官方给的题解比我的简单很多

看代码就马上知道,其思路了

 

 

#include <bits/stdc++.h>
using namespace std;
int main()
{
    long long u,v;
    scanf("%I64d%I64d",&u,&v);
    if (u%2!=v%2 || u>v)
    {
        printf("-1");
        return 0;
    }
    if (u==v)
    {
        if (!u)
        printf("0");
        else
        printf("1\n%I64d",u);
        return 0;
    }
    long long x=(v-u)/2;
    if (u&x)
    printf("3\n%I64d %I64d %I64d",u,x,x);
    else
    printf("2\n%I64d %I64d",(u^x),x);
}

 

 

 

 

就是x和y,如果前面条件都符合,最后如果u=(y-x)/2,当u和x有交集的情况,就是三个x,x,u(x^x=0),如果没交集就可以合并u^x,x

 

posted @ 2020-03-15 12:55  ouluy  阅读(147)  评论(0编辑  收藏  举报