文章目录
Codeforces Round #655 (Div. 2)解题报告
A - Omkar and Completion
思路
一开始还在思考怎么构造,然后通篇没看见说构造的元素不能重复,那就全1好了……
代码
//
// Created by Visors on 2020/7/11.
//
#include <iostream>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
for (int i = 1; i < n; i++) cout << 1 << ' ';
cout << 1 << endl;
}
return 0;
}
B - Omkar and Last Class of Math
思路
求的是LCM,那么会有如下分析:
b
=
n
−
a
b=n-a
b=n−a
L
C
M
(
a
,
b
)
=
L
C
M
(
a
,
n
−
a
)
LCM(a,b)=LCM(a,n-a)
LCM(a,b)=LCM(a,n−a)
假设 a ≤ n − a < n a\leq n-a<n a≤n−a<n,那么有 a ≤ n 2 a\leq \frac{n}{2} a≤2n,且
- 若 a ∣ ( n − a ) a\mid (n-a) a∣(n−a),那么 L C M ( a , n − a ) = n − a < n LCM(a,n-a)=n-a<n LCM(a,n−a)=n−a<n
- 若 a ∤ ( n − a ) a\nmid (n-a) a∤(n−a),那么 L C M ( a , n − a ) = k ∗ ( n − a ) LCM(a,n-a)=k*(n-a) LCM(a,n−a)=k∗(n−a),其中 k > 1 k>1 k>1且为整数,那么显然 L C M ( a , n − a ) ≥ 2 ∗ ( n − a ) ≥ n > n − a LCM(a,n-a)\geq 2*(n-a)\geq n > n-a LCM(a,n−a)≥2∗(n−a)≥n>n−a
由上推论,易知若有 1 1 1,则取 1 1 1情况可以得到比其他 2 2 2情况更好的结果。因为有 a ∣ ( n − a ) a\mid (n-a) a∣(n−a),所以有 n − a = k ∗ a n-a=k*a n−a=k∗a且 n = ( k + 1 ) ∗ a n=(k+1)*a n=(k+1)∗a,由是我们可以令 a n s = n ans=n ans=n,从小到大枚举 k k k,因为 n n n为定值不变,所以 k k k越小, a a a越大,从而 n − a n-a n−a越小,即 L C M ( n , n − a ) LCM(n,n-a) LCM(n,n−a)越小。按此推论写出代码即可。
代码
//
// Created by Visors on 2020/7/11.
//
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
int ans = n;
int len = sqrt(n);
for (int i = 2; i <= len; i++)
if (n % i == 0) {
ans = i;
break;
}
cout << n / ans << ' ' << n - n / ans << endl;
}
return 0;
}
C - Omkar and Baseball
思路
首先认识一点,由于数字是 1 ∼ n 1\sim n 1∼n,所以对于从小到大的有序数列有 a i = i a_i=i ai=i,我们暂且称满足该式的 a i a_i ai称为在原位,不满足该式的称为错位。
题目看上去有点难,仔细分析,其实任意数列需要的最小操作次数都不会超过 2 2 2
- 不用操作:如果数列本就有序,当然不用操作。
- 操作一次:显然,如果给定的序列中有且仅有一串连续的错位数字(也可能是一个数字),则一次操作对这串(这个)数字进行特殊交换,即可得到各个数字都在原位的序列。
- 操作两次:如果给定的序列有多串(不同串间被在原位的数字隔开)连续的错位数字(同样也可能是一个数字),思考我们可以找到第一个错位的数字和最后一个错位的数字,然后对这个区间内的数字进行特殊交换。怎么做这次交换呢?一次交换就想把这串数字归位显然是不行的,我们可以先将这串数字打乱,使得他们全部错位,然后再特殊交换一次,使他们全部归位。
代码
//
// Created by Visors on 2020/7/11.
//
#include <iostream>
#include <vector>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<int> v(n);
for (auto &it:v) {
cin >> it;
it--;
}
bool flag = true;
for (int i = 1; i < v.size(); i++)
if (v[i - 1] > v[i]) {
flag = false;
break;
}
if (flag) {
cout << 0 << endl;
continue;
}
int status = 0, ans = 1; // status: 0-都是原位 1-有连续错位 2-错位后又有原位
for (int i = 0; i < v.size(); i++) {
if (v[i] == i) {
if (status == 1) status = 2;
} else {
if (status == 0) status = 1;
else if (status == 2) {
ans = 2;
break;
}
}
}
cout << ans << endl;
}
}
D - Omkar and Circle
过些时日再整理