A.Omkar and Completion
题目描述
要求你找出一个序列a,满足序列a对于任意的x,y,z都满足:
a
x
+
a
y
≠
a
z
a_x + a_y ≠ a_z
ax+ay=az
并且满足ai <= 1000
题解:
一开始我还想打个奇数表啥的…
但是看见元素值要求小于1000就放弃了,因为第1000大的奇数早就爆了…
其实这个题很简单,都是1不就好了QAQ
AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e5;
int a[maxn] = {};
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
题目描述:
给定一个数n,要求找出两个正整数满足
a
+
b
=
n
a + b = n
a+b=n
和
L
C
M
(
a
,
b
)
−
>
m
i
n
LCM(a,b) -> min
LCM(a,b)−>min
题解:
首先我们知道的是,lcm的值最小就是a,b,其中之一,那么我们就去找b是a的倍数的情况。那么我们可以得到,a就是n的倍数
a
=
x
;
b
=
k
x
;
a
+
b
=
n
则
有
n
=
K
x
a = x; b = kx; a + b = n则有n = Kx
a=x;b=kx;a+b=n则有n=Kx
所以我们需要枚举一下n的倍数,而且要求lcm的值最小其实就是要求a的值尽可能大,最大不会超过n/2(O(n)),所以枚举一下答案就可以
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
int t,a = 1,b;
cin >> t;
while(t--){
int n;
cin >> n;
a = 1;
b = n - 1;
for(int i = 2;i <= sqrt(n);i++){ //注意这里枚举的其实是上面说的K的值
if(n % i == 0){
a = n/i;
b = n - n/i;
break;
}
}
cout << a << ' ' << b << endl;
}
return 0;
}
C.Omkar and Baseball
题目描述:
给你一个随机序列a,现在规定一种排序方法:对于任意区间内的元素,我们可以对他们进行重新排序,但是要求每个元素都不能在他之前的位置上,现在问对于一个随机序列,你需要做几次这样的操作才能实现序列有序(规定为升序)?
题解:
这个题目我们可以这样考虑:
对于一个序列而言,如果该元素的位置是正确的,那么我们就不需要对它进行重新排序了,所以这个问题转化为:找这个序列中所有的不连续的错排序列,这样最后找出来的连续错排序列就是答案了。
AC题解:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 2e5 + 19;
int a[maxn] = {};
int main()
{
int t;
cin >> t;
while(t--){
memset(a,0,sizeof(a));
int n,sum = 0;
cin >> n;
for(int i = 1;i <= n;i++) cin >> a[i];
for(int i = 1;i <= n;i++) //连续不正确序列数目
if(a[i] != i && a[i - 1] == i - 1) sum++;
if(sum >= 2) cout << 2 << endl;
else cout << sum << endl;
}
return 0;
}
D.Omkar and Circle
题目描述:
给出一个环形,现在可以将与某一个数相邻的两个数相加后来代替这个数,一直操作到这个环中还剩下一个数,现在问你最后得到的最大值可以是多少。
题解:
我们分析一下这个操作:
把一个数替换成它的两边的数之和,其实就是每一次减去一个数,而且这些数不能相邻,问最后剩下的元素和最大会是多少。
所以我们可以维护每个元素的不相邻的前缀和后缀和,最后找到二者相加最大的值就是最后答案。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int maxn = 2e5 + 19;
ll a[maxn] = {},b[maxn] = {},c[maxn] = {};
int main()
{
int n,cnt = 0,num;
cin >> n;
num = n;
for(int i = 1;i <= n;i++) cin >> a[i];
for(int i = 1;i <= n;i++){ //统计前缀和
if(i <= 2) b[++cnt] = a[i];
else b[++cnt] = a[i] + b[i - 2];
}
for(int i = n;i >= 1;i--){ //统计后缀和
if(i >= n - 1) c[num--] = a[i];
else c[num--] = a[i] + c[i + 2];
}
ll ans = 0;
for(int i = 1;i <= n;i++){ //找最大
ans = max(ans,b[i] + c[i + 1]); //当前元素的前缀加后一个元素的后缀
}
cout << ans << endl;
return 0;
}