Educational Codeforces Round 58 A,B,C,D,E,G

A. Minimum Integer

链接:http://codeforces.com/contest/1101/problem/A

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main()
{
    int n,x,y,d;
    cin >> n;
    for(int i = 1;i <= n;i ++){
        cin>>x>>y>>d;
        if(x > d) cout<<d<<endl;
        else {
            int k = y/d+1;
            cout<<k*d<<endl;
        }
    }
    return 0;
}

B. Accordion

链接:http://codeforces.com/contest/1101/problem/B

思路:给你一个字符串你可以删除任何一个字符,问能组成最长的符合要求的字符长度。要求为:开头必须为[:结尾必须为:],中间可以有任意数量的|,我们只要找到最先出现的[:和最后出现的:],然后统计下两个:之间有多少个|就好了

实现代码;

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main()
{
    string s;
    cin>>s;
    int flag = 0;
    int len = s.size();
    int st = -1,ed = -1,t = -1,d = -1;
    for(int i = 0;i < len;i ++){
        if(s[i]=='['&&flag == 0){
            flag = 1;st = i;
        }
        if(flag==1&&s[i]==':'){
            t = i;break;
        }
    }
    flag = 0;
    for(int i = len-1;i >= 0;i --){
        if(s[i]==']'&&flag == 0)flag = 1,ed=i;
        if(flag==1&&s[i]==':'){
            d = i;break;
        }
    }
   // cout<<st<<" "<<ed<<" "<<t<<" "<<d<<endl;
    if(st==-1||ed==-1||t==-1||d==-1||t>=d||st>ed)
        cout<<-1<<endl;
    else{
        int ans = 0;
        for(int i = t;i <= d;i ++){
            if(s[i]=='|') ans++;
        }
        cout<<4+ans<<endl;
    }
}

C. Division and Union

链接:http://codeforces.com/contest/1101/problem/C

思路:要求两个集合内的区间不能有重合的,那么我们只要找到有一段有间隔的将前一部分设为集合1,后部分设为集合二,那么两个集合绝对不会存在交集

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int M = 2e5 + 10;

struct node{
    int x,y,id;
}a[M];

int ans[M];
bool cmp(node a,node b){
     if(a.x == b.x) return a.y < b.y;
     return a.x < b.x;
}

int main()
{
    int t,n;
    cin>>t;
    while(t--){
        cin>>n;
        int mx = 0;
        for(int i = 1;i <= n;i ++){
            cin>>a[i].x>>a[i].y;
            a[i].id = i;
            mx = max(a[i].y,mx);
        }
        sort(a+1,a+1+n,cmp);
        int ed = a[1].x,flag = 0;
        for(int i = 1;i <= n;i ++){
            if(a[i].x > ed&&flag == 0) flag = 1;
            if(flag==0) ans[a[i].id] = 1;
            else ans[a[i].id] = 2;
            ed = max(ed,a[i].y);
        }
        if(!flag) cout<<-1<<endl;
        else {
            for(int i = 1;i <= n;i ++){
                cout<<ans[i]<<" ";
            }
            cout<<endl;
        }
    } rn 0;
}

D. GCD Counting

题意:

给你一颗树,树上各个点有权值,要求gcd(x,y) > 1的情况下 树上最长的长度,gcd(x,y)就是求树上x到y路径上所有点权值的gcd

思路:

要想x-y路径上gcd大于1,那么路径上的数都要是某个大于1的数的倍数,对一个数我们可以求出他可以为哪些数的倍数,所有数求完之后对于一个数我们也可以知道他在这棵树里有哪些数是他的倍数,我们每次标记下这些点为可用点,然后dfs求下当前点最远能到哪里(只能走可用点),然后比较与之前的最大长度比较。这样每个都跑完最大的就是答案。

实现代码: 

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int M = 2e5 + 10;

int vis[M],ans,a[M];
vector<int>g[M],v[M];
int dfs(int u){
    int mx = 0;
    vis[u] = 0;
    for(int i = 0;i < g[u].size();i ++){
         int v = g[u][i];
         if(!vis[v]) continue;
         int k = dfs(v);
         ans = max(ans,k+1+mx);
         mx = max(mx,k);
    }
    ans = max(ans,1);
    return mx + 1;
}

int main()
{
    int n,x,y;
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++){
        scanf("%d",&a[i]);
        for(int j = 1;j*j <= a[i];j ++){
            if(a[i]%j) continue;
            v[j].push_back(i);
            if(j*j != a[i]) v[a[i]/j].push_back(i);
        }
    }
    for(int i = 1;i < n;i ++){
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    for(int i = 2;i <= M;i ++){
        for(int j = 0;j < v[i].size();j ++) vis[v[i][j]] = 1;
        for(int j = 0;j < v[i].size();j ++)
            if(vis[v[i][j]]) dfs(v[i][j]);
    }
    cout<<ans<<endl;
    return 0;
}

E. Polycarp's New Job

链接:

思路:题目上写了要求,if either xh and yw or yh and xw.按这个要求写个判断,记录下输入的最大长和宽,如果宽大于长,那么调换下位子,最后用题目要求判断下就好了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int M = 2e5 + 10;
int n,x,y,mx,my;
int main()
{
    char op[3];
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++){
        scanf("%s",op);
        scanf("%d%d",&x,&y);
        if(op[0]=='+'){
        if(x > y) swap(x,y);
        mx = max(mx,x);
        my = max(my,y);
        }
        else{
            int flag = 0;
            if(mx<=x&&my<=y) flag = 1;
            if(mx<=y&&my<=x) flag = 1;
            if(flag) printf("YES\n");
            else  printf("NO\n");
        }
    }
    return 0;
}

G. (Zero XOR Subset)-less

链接:http://codeforces.com/contest/1101/problem/G

题目:给你一段序列,你可以把它分成几段,满足任意子集异或和不为0

思路:当序列异或和为0时无解,因为一段的异或和可以用两个前缀异或和求得,我们将每个数异或前缀和处理下扔到线性基里,基底个数就是答案。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M = 1e6+10;
struct Linear_Basis{
    ll b[63],nb[63],tot;
    void init(){
        tot = 0;
        memset(b,0,sizeof(b));
        memset(nb,0,sizeof(nb));
    }

    bool Insert(ll x){
        for(int i = 62;i >= 0;i --){
            if(x&(1LL<<i)){
                if(!b[i]){
                    b[i] = x;
                    break;
                }
                x ^= b[i];
            }
        }
        return x > 0;
    }

    ll Max(ll x){
        ll ret = x;
        for(int i = 62;i >= 0;i --)
            ret = max(ret,ret^b[i]);
        return ret;
    }

    ll Min(ll x){
        ll ret = x;
        for(int i = 0;i <= 62;i ++)
            if(b[i]) ret ^= b[i];
        return ret;
    }

    void rebuild(){
        for(int i = 62;i >= 0;i --)
            for(int j = i-1;j >= 0;j --)
                if(b[i]&(1LL<<j)) b[i]^=b[j];
        for(int i = 0;i <= 62;i ++)
            if(b[i]) nb[tot++] = b[i];
    }

    ll K_Min(ll k){
        ll res = 0;
        if(k >= (1LL<<tot))
            return -1;
        for(int i = 62;i >= 0;i --)
            if(k&(1LL<<i))
                res ^= nb[i];
        return res;
    }
}LB;

int main(){
    int n,x;
        cin>>n;
        LB.init();
        ll ans = 0;
        for(int i = 1;i <= n;i ++){
            cin>>x;
            ans = ans^x;
            LB.Insert(ans);
        }
        int cnt = 0;
        if(ans == 0) cout<<-1<<endl;
        else {
            for(int i = 31;i >= 0;i--)
                if(LB.b[i])  cnt ++;
            printf("%d\n",cnt);
        }

        return 0;
}

猜你喜欢

转载自www.cnblogs.com/kls123/p/10274357.html