A. Distance
- Distance
题意:
给定一个两个点A,B如要求点C,使得A到C的距离和C到B的距离是A到B的距离的一半,注意这里是曼哈顿距离,然后题目又有很多限制,构造一下C的位置就好了
思路:
直接在如果AB距离为奇数直接-1,否则就是沿着B点的水平方向或者竖直方向上一定可以找到一点成立。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
scanf("%d",&t);
while(t--){
int x,y;
scanf("%d%d",&x,&y);
if((x + y)&1)printf("-1 -1\n");
else {
int k = x + y;
k /= 2;
if(x -k >= 0)printf("%d %d\n",x-k,y);
else printf("%d %d\n",x,y-k);
}
}
}
B. Special Permutation
题意:
给你一个长度为偶数的序列,然后再给你左边一般的最小值,和右边一半的最大值,让你构造一个n的排列,如果不能构造,输出-1
思路:
贪心的构造,左边把最大的往里放,右边把最小的往里放,然后判断一下数目够不够,注意左边不能放b,右边不能放a
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,a,b;
scanf("%d%d%d",&n,&a,&b);
vector<int>l,r;
for(int i = n;i > a;i--){
if(i!=b)l.push_back(i);
if(l.size()==n/2-1)break;
}
l.push_back(a);
for(int i = 1;i < b ;i++){
if(i!=a)r.push_back(i);
if(r.size()==n/2-1)break;
}
r.push_back(b);
if(l.size()!=n/2||r.size()!=n/2)printf("-1\n");
else {
for(auto i : l){
printf("%d ",i);
}
for(auto i : r){
printf("%d ",i);
}
printf("\n");
}
}
}
C. Chat Ban
题意:
一个人要发一堆表情,最多发x个,然后问你最多发多少行
思路:
二分一个答案,然后等差数列求一下和,然后就很好判断是否能达到这个行数,注意他这个题目构造的行中的数目先上升在下降,所以要分两段求
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool ok(ll cur,ll k,ll x){
ll ans = 0;
if(cur > k){
ans += (1LL + k) * k / 2;
cur -= k;
ans += (k - 1 + k - cur + 1)*(cur-1)/2;
if(x > ans)return true;
else return false ;
}
else {
ans += (1 + cur - 1)*(cur - 1)/2;
if(x > ans)return true;
else return false ;
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
ll k,x;
scanf("%lld%lld",&k,&x);
ll r = 2*k-1,l = 1;
ll ans = 1;
while(l<=r){
ll mid = (l + r)>>1;
if(ok(mid,k,x)){
l = mid + 1;
ans = max(ans,mid);
}
else r = mid - 1;
}
printf("%lld\n",ans);
}
}
E. Messages
题意:
给你一个a,b,x,然后有两种替换法,把a换成|a - b|,或者把b换成|a-b|,问是否能把a或者b换成x这个数。
思路:
首先我们不妨设a > b,如果不是可以的调换,然后我们如果第一次操作把a ,b变为a, a - b,则第二次操作我们就不能减b的位置了,只能减a的位置a,那么第二次操作后会变成b,a-b,我们我们发现其实就是把大数a减了b,所以我们每次只考虑减大数直到大数减成小数。然后,我们只需要判断减的过程中是否出现把大数减成x的情况就是
a
%
b
=
=
x
%
b
a\%b==x\%b
a%b==x%b(假设
a
>
b
a > b
a>b),然后就是注意一些特判条件,写一个类似辗转相除的写法。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool f(ll a,ll b, ll c){
if(a < b){
swap(a,b);
}
if(a == c||b == c)return true;
else if(a < c)return false;
else if(b == 0)return false;
else if(a % b == c % b)return true;
else {
return f(a%b,b,c);
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
ll a,b,x;
scanf("%lld%lld%lld",&a,&b,&x);
if(a == x || b == x){
printf("YES\n");
}
else if(a < x && b < x){
printf("NO\n");
}
else {
if(a < b)swap(a,b);
if(f(a,b,x)){
printf("YES\n");
}
else printf("NO\n");
}
}
}