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;
}