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;
}
posted @ 2020-08-22 17:18  Luglucky  阅读(235)  评论(0编辑  收藏  举报