Codeforces Round #665 (Div. 2)
A. Distance and Axis
题目描述:
现在在一个数轴上给出一个A点,并要求你找出一个满足的点B,使得OB和AB满足:
∣
O
A
−
A
B
∣
=
k
|OA - AB| = k
∣OA−AB∣=k
n是给出A的坐标,k是上述距离。如果没有办法找到,允许改变A的坐标,即对A的坐标值+1或者-1。
问要找到这个B点需要进行多少次操作。
题解:
这个题目分为这样几种情况考虑:
-
n = 0
,这时ans = k
(因为A点和原点重合,所以说我们就需要找到满足长度为k的OA的长度然后让B和A重合) -
k = 0
,这时ans = ((n & 1) ? 1 : 0)
(B点取中点,但是要考虑是不是偶数长度,否则要+1) -
k > n
,这时ans = k - n
(这个时候就是和第一种情况差不多,因为我们对于确定的n而言,我们能取到的最大k值就是n,所以只需要放大到k就可以满足) -
k < n
,这就有点意思了,我们注意到,k和n奇偶性相同时,这时的答案就是0,但是如果不同,那么答案就是1了,这个可以多试几个数据然后写一下可能产生的情况总结规律。
AC代码:
#include<iostream>
using namespace std;
int main()
{
int t;
cin >> t;
while(t--){
int n,k;
cin >> n >> k;
if(n == 0) cout << k << endl;
else if(k == 0) cout << ((n & 1) ? 1 : 0) << endl;
else if(k == n) cout << 0 << endl;
else if(k > n) cout << k - n << endl;
else if(k < n){
if((n % 2) == (k % 2)){
cout << 0 << endl;
}
else{
cout << 1 << endl;
}
}
}
return 0;
}
B.Ternary Sequence
题目描述:
给定了两个序列a,b,其中的元素都是0,1,2组成的,在a序列中0,1,2的数目分别是x1,y1,z1;b序列中的0,1,2的数目分别是x2,y2,z2。现在给出了一个序列c,满足以下的条件:
c
i
=
a
i
∗
b
i
,
a
i
>
b
i
c_i = a_i * b_i,a_i > b_i
ci=ai∗bi,ai>bi
c i = 0 , a i = b i c_i = 0,a_i = b_i ci=0,ai=bi
c i = − a i ∗ b i , a i < b i c_i = -a_i * b_i,a_i < b_i ci=−ai∗bi,ai<bi
现在要求你写出c的元素之和的最大值。
题解:
这个题目我们可以贪心的去想,我们尽可能让z1和y2匹配,并且尽可能减少z2和y1的匹配。
那么这个题就可以先凑出最大的z1和y2的匹配,然后z1和z2抵消一次,z2和x1抵消一次,这样我们可以得到z2的最小值,然后我们y1和y2抵消一次,然后y1和x2抵消一次,这样得到的就是y1的最小值,然后匹配y1和z2。
AC代码
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
int main()
{
int t;
cin >> t;
while(t--){
ll x1,x2,y1,y2,z1,z2,ans = 0;
cin >> x1 >> y1 >> z1 >> x2 >> y2 >> z2;
ll temp = min(z1,y2); //注意存一下值,因为接下来的z1和y2的值都改变了,这会影响到min的值,后面的同理
ans = temp;
z1 -= temp;
y2 -= temp;
ll flag = min(z1,z2);
z1 -= flag;
z2 -= flag;
ll cnt = min(x1,z2);
z2 -= cnt;
y1 -= min(y1,x2);
y1 -= min(y1,y2);
ans -= min(y1,z2);
cout << ans * 2 << endl;
}
return 0;
}
C.Mere Array
题目描述:
给出了一个既定的序列a,现在规定一种排列方式:对于这个序列中的两个元素,如果满足:
g
c
d
(
a
i
,
a
j
)
=
m
i
n
(
a
)
gcd(a_i,a_j) = min(a)
gcd(ai,aj)=min(a)
那么就可以交换两个元素的位置,现在需要你判断对于一个给出的序列a,能否通过这样的操作使得a变成递增序列。
题解:
既然两个元素的最大公约数是a序列中最小的元素时才能交换次序,那么就是说只有这两个元素是最小值的倍数才满足条件,那么我们可以先把正确的序列排出来,然后和原序列比较,如果位置不正确而且不是最小值倍数的话,那就一定不能交换出正确序列。反之如果对于每个错误的数都是最小值倍数,那么就一定可以通过交换次序得出正确的序列。
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 1e5 + 10;
ll a[maxn],b[maxn];
bool cmd(ll a,ll b)
{
if(a != b) return a < b;
}
int main()
{
int t;
cin >> t;
while(t--){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
int n;
ll min_a = 0x3f3f3f3f;
cin >> n;
for(int i = 1;i <= n;i++){
cin >> a[i];
b[i] = a[i];
min_a = min(a[i],min_a);
}
bool flag = 1;
sort(a + 1,a + 1 + n,cmd);
for(int i = 1;i <= n;i++){
if(a[i] != b[i] && b[i] % min_a != 0){
flag = 0;
break;
}
}
if(flag) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}