Codeforces Global Round 10
A. Omkar and Password
可以任意合并数组相邻不相等的元素,最终数组所有元素都相同,求最短长度。
原数组元素全相同答案为n,反之为1.
B. Omkar and Infinity Clock
每次找出数组最大值,a[i]=mx-a[i],求k(1e18)次后的数组。
模拟了一下发现有规律,根据k的奇偶判断一下就好了。
分析:第一次操作之后,最大值的位置就是原来最小值的位置,之后就是最大最小值不断交换的过程。
if(k&1) {
for(int i=0;i<n;i++) a[i]=mx-a[i];
} else {
for(int i=0;i<n;i++) a[i] -= mi;
} C. Omkar and Waterslide
给定一个序列,每次可以在一个相同高度的子段上+1,求使其变成单调不减序列最小操作次数。
答案就是下降的差值之和,举个例子,5 1 2 3,如果1加到了5那么23肯定也到5了。
for(int i=1;i<n;i++) {
if(a[i]<a[i-1]) sum+=a[i-1]-a[i];
} D. Omkar and Bed Wars
给定包含RL的字符串,分别代表当前位置上的人向右方/左方发起攻击。求最小的更改次数,使其满足:如果当前位置受到单侧攻击则向其反击,受到双侧攻击则向任意一个方向反击。所有人围成的是一个环。
观察一下,合法字符串包括RL RLL RLLR,只要连续出现的次数不超过三次就是合法的。全R或全L需要特判。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t,n,len,ans,cnt;
string s;
int main() {
scanf("%d",&t);
while(t--) {
vector<int> v;
scanf("%d",&n);
cin >> s;
cnt=1; ans=0;
for(int i=1;i<n;i++) {
if(s[i]==s[i-1]) cnt++;
else v.push_back(cnt), cnt=1;
}
if(cnt) v.push_back(cnt);
len = v.size();
if(len==1) {
printf("%d\n", (n+2)/3);
continue;
}
if(s[0]==s[s.length()-1]) v[0]+=v[--len];
for(int i=0;i<len;i++)
ans+=v[i]/3;
printf("%d\n",ans);
}
} E. Omkar and Duck
这是一道交互题。
给定n,要求输出n×n的矩阵,每个值分别代表点 (i,j) 的权值,系统会给出q个合法权值w,每次要求从左上角走到右下角,只能向右或下走,总权值恰好为w且路径唯一。
往二进制的角度思考
如果需要恰好为w:(对角线相等)
加上路径唯一的条件
那么其实就是在每一步判断下一步对应的二进制位上是否有1。
注意:输出后要加上fflush(stdout)(scanf星人表示-_-||),C++ cout<<endl;可以自动清空缓存区。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,q,x,y;
ll t;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(i&1) printf("0 ");
else printf("%lld ",1LL<<(i+j));
}
printf("\n");
}
fflush(stdout);
scanf("%d",&q);
while(q--) {
scanf("%lld",&t);
x = y = 1;
// printf("%d %d\n",x,y);
cout << x << " " << y << endl;
for(int i=1;i<=2*n-2;i++) {
if(x&1) {
if(t&(1LL<<(x+y+1))) x++;
else y++;
} else {
if(t&(1LL<<(x+y+1))) y++;
else x++;
}
cout << x << " " << y << endl;
// printf("%d %d\n",x,y);
}
}
} F. Omkar and Landslide
给定数组h,如果h[i]+2<=h[i+1],则h[i]--,h[i+1]++,一直重复到不能进行操作为止,求最终的数组。
打表找规律,先构造等差数列剩下加1即可。
打表代码
#include <bits/stdc++.h>
#define random(a,b) ((a)+rand()%((b)-(a)+1))
using namespace std;
int n,cnt;
int a[20];
void print(int n) {
for(int i=1;i<=n;i++) {
printf("%d ",a[i]);
}
printf("\n");
}
void init(int n) {
srand((unsigned)time(NULL));
int sum=0;
for(int i=1;i<=n;i++) {
a[i]=random(a[i-1]+1,a[i-1]+8);
sum+=a[i];
}
print(n);
printf("Sum=%d, Sum/n=%.2f\n",sum,1.0*sum/n);
}
int fun(int n) {
for(int i=1;i<n;i++) {
while(a[i]+2<=a[i+1]) {
a[i]++;a[i+1]--;
}
}
}
int check(int n) {
for(int i=1;i<n;i++) {
if(a[i]+2<=a[i+1]) {
return 1;
}
}
return 0;
}
int main() {
n=6;
init(n);
while(check(n)) fun(n);
print(n);
} 解题代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
ll n,sum;
ll a[maxn], ans[maxn];
int main() {
scanf("%lld",&n);
for(int i=0;i<n;i++) scanf("%lld",&a[i]), sum+=a[i];
ans[0]=(2*sum-n*n)/(2*n);
sum-=ans[0];
for(int i=1;i<n;i++) {
ans[i]=ans[i-1]+1;
sum-=ans[i];
}
int j=0;
while(sum>0) {
sum--;
ans[(j++)%n]++;
}
for(int i=0;i<n;i++) {
printf("%lld ",ans[i]);
}
} 
京公网安备 11010502036488号