CF div2 117场次
A题(原题网址 )
大致题意
在坐标轴上给定两点 分别为 A(0, 0), B(x, y),定义一个函数 d(A, B) = |Xa - Xb| + |Ya - Yb|
问是否能找到一点 C 使得
d(A, C) = d(A, B) / 2
d(B, C) = d(A, B) / 2
其中 Xc, Yc >= 0
AC代码
#include <iostream>
#include<algorithm>
using namespace std;
int main(){
int t;
int x, y;
scanf("%d", &t);
while(t--){
scanf("%d%d", &x, &y);
if(x == y) printf("0 %d\n", y);
else if(x == 0){
if(y & 1) printf("-1 -1\n");
else{
printf("0 %d\n", y >> 1);
}
}else if(y == 0){
if(x & 1) printf("-1 -1\n");
else{
printf("%d 0\n", x >> 1);
}
}else{
if(x % 2 == 0 && y % 2 == 0){
printf("%d %d\n", x >> 1, y >> 1);
}else{
for(int i = 0; i <= x; i++){
for(int j = 0; j <= y; j++){
if(i + j == abs(x - i) + abs(y - j) && i + j == (x + y) >> 1){
printf("%d %d\n", i, j);
goto con;
}
}
}
printf("-1 -1\n");
con: continue;
}
}
}
}
B题(原题网址)
大致题意
给定你 n, a, b
, 要你构造一个长度为n(n为偶数)的一个数组,数组中的元素由 1 ~ n 组成,无重复数字。要求: 在左半区间a最小,右半区间b最大
,若能则输出其中任意一个,若不能构造这样的区间则输出-1
AC代码
#include <iostream>
#include<algorithm>
#include <cstring>
using namespace std;
int arr[110];
bool vis[110];
int main(){
int t;
int n, l, r;
scanf("%d", &t);
while(t--){
memset(arr, 0 , sizeof arr);
memset(vis, false , sizeof vis);
scanf("%d%d%d", &n, &l, &r);
if(n - l + 1 < ( n >> 1 ) || r < (n >> 1) || max( l, r) <= (n>>1)|| min(l, r) > (n >> 1)){
printf("-1\n");
continue;
}
arr[1] = l, arr[n] = r;
vis[l] = vis[r] = true;
int idx = n;
for(int i = 1 ; i <= n; i++){
if(!arr[i]){
while(vis[idx]) idx--;
arr[i] = idx;
vis[idx] = true;
}
}
for(int i = 1; i <= n; i++)
printf("%d ", arr[i]);
printf("\n");
}
}
C题(原题网址)
大致题意
给定k, x
,k会构成一个2 * k - 1 的图案,如下
/*
* k = 1
* 排列为 -- >
* *
* k = 2
* 排列为 -- >
* *
* * *
* *
* k = 3
* 排列为 -- >
* *
* * *
* * * *
* * *
* *
*/
你想在一个聊天室发由k
构造而成的图案,每次发一行,而 x 则是对 * 的数量的限制。
只要你发的 * 的数量超过了 x 就会被禁言,问你发多少行会被禁言,如果都不会被禁言就输出你最多发了多少行(可自行去原题网址查看样例数据)
AC代码
#include <iostream>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
int main(){
int t;
ll k, x;
scanf("%d", &t);
while(t--){
scanf("%lld%lld", &k, &x);
ll len = (k << 1) - 1;
ll l = 1, r = len;
ll sum;
while(l <= r){
ll mid = (l + r) >> 1;
if(mid <= k){
sum = (mid + 1) * mid >> 1;
if(sum < x) l = mid + 1;
else r = mid - 1;
}else{
ll lr = len - mid;
sum = ((k + 1) * k >> 1) + ((k - 1) * k >> 1) - ((lr + 1) * lr >> 1);
if(sum < x) l = mid + 1;
else r = mid - 1;
}
}
if(l > len) printf("%d\n", r);
else printf("%d\n", l);
}
}
D题(原题网址)
大致题意
给定 a, b, x
你可以将 a 或 b
替换成 |a - b| (|a - b| != a 或 b)
问:在进行任意次操作后是否有 a 或 b 等于 x
的情况, 有则输出 YES
反之输出 NO
如 a b c
6 9 3
||
\/
6 3 3 此时 b = 3 = x
||
\/ (还可继续操作)
3 3 3
AC代码
#include <iostream>
#include <algorithm>
#include <cstring>
#define no printf("NO\n")
#define yes printf("YES\n")
#define ll long long
using namespace std;
ll ta, tb, x;
bool find(ll a, ll b){
if(max(a, b) < x) return false;
if(a == x || b == x || abs(a - b) == x) {
yes;
return true;
}
if(abs(a - b) == a || abs(a - b) == b) return false;
if(a > b){
a -= ((a - x) / b )* b;
}else{
b -= (b - x) / a * a;
}
if(a == x || b == x || abs(a - b) == x) {
yes;
return true;
}
if(find(min(a, b), abs(a - b))) return true;
return false;
}
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%lld%lld%lld", &ta, &tb, &x);
if(x > max(ta, tb)) no;
else{
if(ta == x || tb == x) yes;
else if(!find(ta, tb)) no;
}
}
}