A. Distance
题目概述:
问在点
A
(
0
,
0
)
A(0, 0)
A(0,0) 和点
B
(
x
,
y
)
B(x, y)
B(x,y) 之间能否找到一点
D
(
a
,
b
)
a
,
b
∈
Z
∗
D(a, b) a, b\in Z^*
D(a,b)a,b∈Z∗ ,使得从
A
A
A 到
D
D
D,从
D
D
D 到
B
B
B,的哈曼顿距离相等,如果存在输出坐标,如果不存在输出
−
1
−
1
-1 -1
−1−1。
思路:
当
x
+
y
x + y
x+y 为奇数时候,即A到B的哈曼顿距离无法背拆成两段,则无论怎么样也找不出点
D
D
D。
当
x
+
y
x + y
x+y 为偶数的时候,可以拆为两段,坐标可以为 (
⌊
x
2
⌋
\lfloor \frac{x}{2}\rfloor
⌊2x⌋,
⌈
x
2
⌉
\lceil \frac{x}{2}\rceil
⌈2x⌉)
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --) {
int a, b ;
cin >> a >> b;
if((a + b) % 2) {
cout << -1 << ' ' << -1 << '\n';
} else {
int x = (a + 1) / 2, y = b / 2;
cout << x << ' ' << y << '\n';
}
}
return 0;
}
B. Special Permutation
题目概述:
找到一个
1
1
1 ~
n
n
n 的排列,使得左侧一半的数字最小值为
a
a
a, 右侧一半的数字中的最大值为
b
b
b。如果不能找到 输出
−
1
-1
−1。
思路:
分类讨论一下,太麻烦具体看代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --) {
int n, a, b;
cin >> n >> a >> b;
int s[n + 1];
for(int i = 1; i <= n; i ++) s[i] = i;
reverse(s + 1, s + n + 1);
if(a > b) {
if(a == n / 2 + 1 && b == n / 2) {
for(int i = 1; i <= n; i ++) cout << s[i] << ' ';
cout << '\n';
} else {
cout << -1 << '\n';
}
}else if((a > (n / 2) && b > (n / 2)) || (a <= (n / 2) && b <= (n / 2))) {
cout << -1 << '\n';
} else {
cout << a << ' ';
for(int i = 1; i <= n / 2; i ++) {
if(s[i] == b || s[i] == b) continue;
cout << s[i] << ' ';
}
cout << b << ' ';
for(int i = n / 2 + 1; i <= n; i ++) {
if(s[i] == a || s[i] == b) continue;
cout << s[i] << ' ';
}
cout << '\n';
}
}
return 0;
}
C. Chat Ban
题目概述:
给出
k
k
k
x
x
x,和一个
a
i
a_i
ai:
1
,
2
,
3.....
k
−
1
,
k
,
k
−
1
,
.
.
.
.
.
3
,
2
,
1
1,2,3.....k - 1, k, k - 1,.....3,2,1
1,2,3.....k−1,k,k−1,.....3,2,1的排列。问满足
∑
i
=
1
p
a
i
≤
x
\sum_{i=1}^{p}a_i \le x
∑i=1pai≤x 的
p
p
p 的值是多少。
思路:
本题数据范围很大,所以不考虑预处理,利用等差数列求和公式,对于
a
i
≤
k
a_i \le k
ai≤k 的部分, 可以做一次二分确定位置。如果在
a
i
>
k
a_i \gt k
ai>k 的位置,就将整个翻转 利用
a
i
a_i
ai的总和减去
x
x
x 来得到还剩下多少不能输出的; 即
k
2
−
x
k^2 - x
k2−x。 然后用上面相同的方式来进行二分。由于前面是从上往下求,后面为从下往上求,所以是否取等号需要区别一下。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
using ll = long long;
typedef pair<int, int> PII;
ll k, x;
void solve() {
cin >> k >> x;
ll sum = (k + 1) * k / 2;
if(x >= k * k) {
cout << 2 * k - 1 << '\n';
return;
}
if(x <= sum) {
ll l = 0, r = k;
while(l < r) {
ll mid = (l + r) / 2;
if((1 + mid) * mid / 2 >= x) r = mid;
else l = mid + 1;
}
cout << l << '\n';
return;
}
ll l = 1, r = k ;
x = k * k - x;
while(l < r) {
ll mid = (l + r) / 2;
if((1 + mid) * mid / 2 > x) r = mid;
else l = mid + 1;
}
cout << k - l + k << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --) {
solve();
}
}
D. X-Magic Pair
题目概述:
一对整数
(
a
,
b
)
(a, b)
(a,b),问能不能通过不断修改
a
a
a 或者
b
b
b 的值为
∣
a
−
b
∣
|a - b|
∣a−b∣,来使得新得到的
(
a
,
b
)
(a,b)
(a,b) 中的任意一个等于
x
x
x。
思路:
本题数据范围过大,之间相减然后模拟显然会运行超时。
考虑在取模代替减法,如果满足:
- b b b % a = x a = x a=x % a a a ( b > a b > a b>a),即 a , b a,b a,b 中较大数与 x x x 同余。
-
a
,
b
a,b
a,b 中较大数大于
x
x
x。
就说明可以通过 a , b a,b a,b 构造出 x x x。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
ll a, b, x;
void solve() {
cin >> a >> b >> x;
while(a && b) {
if(a > b) swap(a, b);
if((b % a == x % a) && x <= b) {
cout << "YES" << '\n';
return;
}
b %= a;
}
cout << "NO" << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --) solve();
return 0;
}