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;
    }
    
  • 相关阅读:
    mysql BETWEEN操作符 语法
    mysql IN操作符 语法
    mysql LIKE通配符 语法
    mysql TOP语句 语法
    mysql DELETE语句 语法
    mysql Update语句 语法
    mysql INSERT语句 语法
    mysql ORDER BY语句 语法
    mysql OR运算符 语法
    mysql AND运算符 语法
  • 原文地址:https://www.cnblogs.com/hhlya/p/13546357.html
Copyright © 2011-2022 走看看