zoukankan      html  css  js  c++  java
  • Codeforces Round #665 (Div. 2) 题解

    Problem A

    题面

    We have a point A with coordinate x=n on OX-axis. We'd like to find an integer point B (also on OX-axis), such that the absolute difference between the distance from O to B and the distance from A to B is equal to k.

    The description of the first test case.
    Since sometimes it's impossible to find such point B, we can, in one step, increase or decrease the coordinate of A by 1. What is the minimum number of steps we should do to make such point B exist?

    Input
    The first line contains one integer t (1≤t≤6000) — the number of test cases.

    The only line of each test case contains two integers n and k (0≤n,k≤106) — the initial position of point A and desirable absolute difference.

    Output
    For each test case, print the minimum number of steps to make point B exist.

    思路

    首先我们讨论这个差值是否为0,这时如果n为偶数,那么必然成立(取中点),奇数的话答案就是1,然后如果差值大于区间,直接减就好了,小于的话分奇偶讨论就好了,比赛的时候代码写复杂了。

    代码实现

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=getchar();
        } while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        } return x*f;
    }
    
    int main () {
        int t;
        cin>>t;
        while (t--) {
            int n,k;
            cin>>n>>k;
            if (k==0) {
                if (n%2==0) {
                    cout<<0<<endl;
                    continue;
                }
                else {
                    cout<<1<<endl;
                    continue;
                }
            }
            else if (k==n) {
                cout<<0<<endl;
                continue;
            }
            else if (k>n) {
               cout<<abs(n-k)<<endl;
               continue;
            }
            else if (k<n) {
                if (n%2==1) {
                    if (k%2==1) {
                        cout<<0<<endl;
                    }
                    else {
                        cout<<1<<endl;
                    }
                }
                else if (n%2==0) {
                    if (k%2==0) {
                        cout<<0<<endl;
                        continue;
                    }
                    else {
                        cout<<1<<endl;
                        continue;
                    }
                }
            }
        }
    
        return 0;
    }
    

    Problem B

    题面

    You are given two sequences a1,a2,…,an and b1,b2,…,bn. Each element of both sequences is either 0, 1 or 2. The number of elements 0, 1, 2 in the sequence a is x1, y1, z1 respectively, and the number of elements 0, 1, 2 in the sequence b is x2, y2, z2 respectively.

    You can rearrange the elements in both sequences a and b however you like. After that, let's define a sequence c as follows:

    ci=⎧⎩⎨aibi0−aibiif ai>biif ai=biif ai<bi
    You'd like to make ∑ni=1ci (the sum of all elements of the sequence c) as large as possible. What is the maximum possible sum?

    Input
    The first line contains one integer t (1≤t≤104) — the number of test cases.

    Each test case consists of two lines. The first line of each test case contains three integers x1, y1, z1 (0≤x1,y1,z1≤108) — the number of 0-s, 1-s and 2-s in the sequence a.

    The second line of each test case also contains three integers x2, y2, z2 (0≤x2,y2,z2≤108; x1+y1+z1=x2+y2+z2>0) — the number of 0-s, 1-s and 2-s in the sequence b.

    Output
    For each test case, print the maximum possible sum of the sequence c.

    思路

    分类讨论的去贪心就好,每次我们必定是选取a序列中的z和y分别取和b中的y和x相互匹配,剩下的情况再去看看能不能把剩下的b序列的2消耗完就是了(实际上答案是确定的)

    代码实现

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=getchar();
        } while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        } return x*f;
    }
    
    int main () {
        int t;
        cin>>t;
        while (t--) {
            int x1,y1,z1;
            int x2,y2,z2;
            int ans=0;
            scanf ("%d%d%d",&x1,&y1,&z1);
            scanf ("%d%d%d",&x2,&y2,&z2);
            int fir=min (z1,y2);
            z1-=fir,y2-=fir;
            int sec=min (y1,x2);
            x2-=sec,y1-=sec;
            ans+= 2*fir;
            if (y1==0&&y2==0) {
               cout<<ans<<endl;
            }
            else if (y1==0&&z1==0) {
                cout<<ans<<endl;
            }
            else if (x2==0&&y2==0) {
                if ((z2-z1-x1)>0) {
                    ans-=(2*(z2-z1-x1));
                    cout<<ans<<endl;
                }
                else {
                    cout<<ans<<endl;
                }
            }
            else if (z1==0&&x2==0) {
                int thir=min (y1,y2);
                y1-=thir,y2-=thir;
                if (y1==0) {
                   cout<<ans<<endl;
                }
                else {
                    if ((z2>x1)) {
                        ans-=2*(z2-x1);
                        cout<<ans<<endl;
                    }
                    else {
                        cout<<ans<<endl;
                    }
                }
            }
        }
        return 0;
    }
    

    Problem C

    题面

    You are given an array a1,a2,…,an where all ai are integers and greater than 0.

    In one operation, you can choose two different indices i and j (1≤i,j≤n). If gcd(ai,aj) is equal to the minimum element of the whole array a, you can swap ai and aj. gcd(x,y) denotes the greatest common divisor (GCD) of integers x and y.

    Now you'd like to make a non-decreasing using the operation any number of times (possibly zero). Determine if you can do this.

    An array a is non-decreasing if and only if a1≤a2≤…≤an.

    Input
    The first line contains one integer t (1≤t≤104) — the number of test cases.

    The first line of each test case contains one integer n (1≤n≤105) — the length of array a.

    The second line of each test case contains n positive integers a1,a2,…an (1≤ai≤109) — the array itself.

    It is guaranteed that the sum of n over all test cases doesn't exceed 105.

    Output
    For each test case, output "YES" if it is possible to make the array a non-decreasing using the described operation, or "NO" if it is impossible to do so.

    思路

    首先我们判断那些是最小值的倍数,然后对数组排序,和原数组对比,如果值不相同,那么说明它是被换过来的,那么我们判断它是否是最小值的倍数就行了,如果序列中有一个不是,那么就不能成立。

    代码实现

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=getchar();
        } while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        } return x*f;
    }
    
    const int maxn=1e5+10;
    int t ;
    int a[maxn],b[maxn];
    int mark[maxn];
    
    int main () {
        cin>>t;
        while (t--) {
            int n;
            scanf ("%d",&n);
            int st;
            int flag=0;
            MT (mark,0);
            rep (i,1,n) {
                scanf ("%d",&a[i]);
                b[i]=a[i];
            }
            sort (b+1,b+n+1);
            rep (i,1,n) {
                if (a[i]%b[1]==0) mark[i]=1;
            }
            rep (i,1,n) {
                if (mark[i]==1 ) continue;
                if (a[i]!=b[i]) flag=1;
            }
            if (flag==0) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
        return 0;
    }
    

    Problem D

    题面

    You are given a tree that consists of n nodes. You should label each of its n−1 edges with an integer in such way that satisfies the following conditions:

    each integer must be greater than 0;
    the product of all n−1 numbers should be equal to k;
    the number of 1-s among all n−1 integers must be minimum possible.
    Let's define f(u,v) as the sum of the numbers on the simple path from node u to node v. Also, let ∑i=1n−1∑j=i+1nf(i,j) be a distribution index of the tree.

    Find the maximum possible distribution index you can get. Since answer can be too large, print it modulo 109+7.

    In this problem, since the number k can be large, the result of the prime factorization of k is given instead.

    Input
    The first line contains one integer t (1≤t≤100) — the number of test cases.

    The first line of each test case contains a single integer n (2≤n≤105) — the number of nodes in the tree.

    Each of the next n−1 lines describes an edge: the i-th line contains two integers ui and vi (1≤ui,vi≤n; ui≠vi) — indices of vertices connected by the i-th edge.

    Next line contains a single integer m (1≤m≤6⋅104) — the number of prime factors of k.

    Next line contains m prime numbers p1,p2,…,pm (2≤pi<6⋅104) such that k=p1⋅p2⋅…⋅pm.

    It is guaranteed that the sum of n over all test cases doesn't exceed 105, the sum of m over all test cases doesn't exceed 6⋅104, and the given edges for each test cases form a tree.

    Output
    Print the maximum distribution index you can get. Since answer can be too large, print it modulo 109+7.

    Example
    inputCopy
    3
    4
    1 2
    2 3
    3 4
    2
    2 2
    4
    3 4
    1 3
    3 2
    2
    3 2
    7
    6 1
    2 3
    4 6
    7 3
    5 1
    3 6
    4
    7 5 13 3
    outputCopy
    17
    18
    286

    思路

    意思就是让我们求如何在保证边权乘积是所给质因子之和的同时,求出我上面所给式子的最大值。那么很显然,我们dfs就好了,需要关注的就是我们需要dfs出来一个数组,这个数组存的是当前这条边会被走过多少次。

    代码实现

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    const int mod=1e9+7;
    typedef long long ll;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=getchar();
        } while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        } return x*f;
    }
    
    int t,n;
    const int maxn=1e5+10;
    ll a[maxn],p[maxn];
    vector <ll> G[maxn],vt,vm;
    ll sz[maxn];
    
    inline void dfs (ll now,ll pre) {
        sz[now]=1;
        for (auto &it:G[now]) {
            if (it==pre) continue;
            dfs (it,now);
            sz[now]+=sz[it];
        }
    }
    
    inline void dfs2 (ll now,ll pre) {
        for (auto &it:G[now]) {
            if (it==pre) continue;
            vm.push_back (sz[it]*(n-sz[it]));
            dfs2 (it,now);
        }
    }
    
    void solve () {
       cin>>n;
    //    rep (i,1,n) sz[i]=0;
       rep (i,1,n) G[i].clear ();
       rep (i,1,n-1) {
           ll x,y;
           scanf ("%lld%lld",&x,&y);
           G[x].pb (y);
           G[y].pb (x);
       }
       int m;
       scanf ("%d",&m);
       rep (i,1,m) scanf ("%lld",&p[i]);
       sort (p+1,p+m+1);
       vt.clear ();
       vm.clear ();
       if (m<=n-1) {
          rep (i,1,n-1-m) vt.pb (1);
          rep (i,1,m) vt.pb (p[i]); 
       }
       else {
          ll now=1;
          rep (i,1,n-2) vt.pb (p[i]);
          rep (i,n-1,m) now=(now*p[i])%mod;
          vt.pb (now);
       }
       dfs (1,0);
       dfs2 (1,0);
       int ans=0;
       sort (vm.begin(),vm.end ());
       for (auto &it:vm) it%=mod;
       rep (i,0,n-2) ans= (ans+vt[i]*vm[i]%mod)%mod;
       cout<<ans<<endl;
    }
    
    int main () {
        cin>>t;
        while (t--) {
            solve ();
        } 
        return 0;
    }
    
  • 相关阅读:
    valgrind 内存调试工具
    centos7 firewall 相关
    linux timer operate
    string int 相互转换
    shared_ptr(作为局部变量返回)
    计算机网络--02物理层
    计算机网络学习笔记--01概述
    java基础---字符串string
    java基础--static关键字的使用
    java基础---java语言概述
  • 原文地址:https://www.cnblogs.com/hhlya/p/13546357.html
Copyright © 2011-2022 走看看