传送门 :Dashboard - Codeforces Round #821 (Div. 2) - Codeforceshttps://codeforces.com/contest/1733A:
A |
题意大致为给定t组测试用例。每组给有n个数的数组a和一个k,你最多可以选择以下k次操作:
从数组a中选择下标为 i 和 j 的两个数
如果 i % k == j % k的话,可以选择交换 a[i] 和 a[j] 的值.
找到一个连续的字串,其长度为k,且字串和最大。
题解:
从输入的时候,就将取模后最大的数存到下标为 0~k - 1的数组中,1 ~ k-1正好是 任何正整数模k的所有可能结果,所以,当输入完时,数组中 前 k 个元素中,每个元素的值就是每个下标等于 i % k的数的最大的那一个然后把前k个数加起来输出即可。
ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e2 + 10;
int t,k,n,x;
LL sum;
int a[N];
int main()
{
cin >> t;
while(t -- )
{
sum = 0;
cin >> n >> k;
for(int i = 1;i <= n;i ++ )
{
cin >> x;
a[i % k] = max(a[i % k],x); // 前1 - k个元素中只存最大的。
}
for(int i = 0;i < k;i ++ )
sum += a[i];
cout << sum << endl;
fill(a, a + k, 0);
}
return 0;
}
B. Rule of League
B |
inputCopy
5
5 2 0
8 1 2
3 0 0
2 0 1
6 3 0
outputCopy
1 1 4 4
-1
-1
2
-1
题目大意:
有n个人打羽毛球比赛,第1个人和第2个人先打,胜者和3打,和3的胜者再和4打...直到和第n个人打完,赢的人就是胜者。
题目给定,每个人只会赢得 x 次比赛或者 y 次比赛。
找到比赛的胜者,并输出每场比赛胜者的编号,多个情况随便输出一个即可。若给定的条件使得不会有胜者,使条件不成立则输出 -1 .
给定t组测试样例和 n x y;
输出每场比赛的获胜者或者 - 1;
题解:
输赢总和一样,总共赢多少场就会总共输多少场。每场比赛都是一个新的人和上一场的获胜者,或者第一个人和第二个人,所以肯定会至少有一个人一场都没赢,所以x和y至少有一个为0;若最终有获胜者,则肯定会有人赢,所以,x,y只能有一个是0,不能同时为0。
现在看情况交换x和y的值,让大的数是x,小的数是y,所以x和y肯定是,x 非0,是一个人获胜的场数,y = 0。
总共只有n个人,所以会打 n - 1场比赛,也就是肯定一共会赢 n - 1次,也输n - 1次,因为每个人只会赢0次和赢 x 次,所以 n - 1一定是x的倍数,(n - 1)% x 一定等于0。
不符合上诉情况的直接输出 -1 continue;
否则:
让第一个人输,剩下 n - 1个人正好可以整除 x,从第二个人开始,输出x次 i (2 <= i <= n),然后i再加个x,知道i等于n为止.
AC代码:
#include<bits/stdc++.h>
using namespace std;
int t,n,x,y;
int main()
{
for(cin >> t;t -- ;)
{
cin >> n >> x >> y;
if(x < y) // x是胜场,y是0
swap(x,y);
if(!x || y || (n - 1) % x)
{
cout << "-1" << endl;
continue;
}
for(int i = 2;i <= n;i += x)
{
for(int j = 0;j < x;j ++ )
{
cout << i << " ";
}
}
cout << endl;
}
return 0;
}
C:
C |
Example
inputCopy
3
2
7 8
5
1 1000000000 3 0 5
1
0
outputCopy
0
2
3 4
1 2
0
题目大意:
给定有n个非负整数的数组a,最多执行 n 次以下操作:
选定两个下标 l 和 r;
如果a[l] + a[r] 的和 为奇数,则让 a[r] = a[l] (前面赋值给后面), 如果和为偶数,则让 a[l] = a[r] (后面赋值给前面)
最多执行 n 次以上操作,使得a数组变成一个非递减的序列。
PS:题目保证一定有解。并且题目让求的 不是需要执行的最少次数,而是找到任何一个满足执行次数小于等于n的情况,输出即可。
给定t组测试样例,每组给定长度n,和数组a的每个值
输出需要的执行次数,如果次数大于0,则再按序每行输出执行操作的 下标l 和 r。
题解:
如果只有一个数,则不需要执行任何操作,直接输出1 continue即可
先让头尾相加比较奇偶,让a[1]和a[n]相等,执行了一次。
现在头尾相等了。中间的数不论和头还是和尾相加,都是奇或者都是偶,所以可以分相加和的奇偶情况。来选择和头还是尾相加,最后使中间的数都和头尾相同。
在从第2个数开始,依次和头(因为现在头=尾,所以也是和尾相加比较)相加比较,如果是奇数,则按规定的操作,选择 l 为 1,r 为 i,让a[r] = a[l],使得第i个数和头(也是尾相同)。
如果是偶数,就选择 l 为 i,r 为 n ,按规则,使 a[l] = a[r],使得第i个数和尾(也是头)相同。
头和尾一共有n - 2个数,所以一共执行 n - 2次。
所以一共需要执行 1 + (n - 2) = n - 1次,得到一个每一位数都相等得数组,满足题意.
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n,t,l,r;
int main()
{
for(cin >> t;t -- ;)
{
cin >> n;
for(int i = 1;i <= n;i ++ )
cin >> a[i];
if(n == 1) // 如果只有一个数,不需要任何操作直接输出即可;
{
cout << "0" << endl;
continue;
}
int cot = n - 1; // 定义需要的操作数,如下操作需要 n - 1次;
cout << cot << endl;
cout << 1 << " " << n << endl; // 先让 A1 + An的值相同,然后从第2个数 至 倒数第2个数 依次和头尾比较
if((a[1] + a[n]) % 2 == 0) // 因为现在头尾的值相同,不管中间的数与头尾相加是奇是偶,都选择能让中间
a[1] = a[n]; // 那个数变成和头尾相同的数,这样就只需要 1(让头尾相同)+ (n-2)(中间依次)
else // 和头尾相同 = n - 1次操作,符合题意.
a[n] = a[1];
for(int i = 2;i < n;i ++ )
{
if((a[i] + a[1]) % 2 != 0)
{
a[i] = a[1];
cout << 1 << " " << i << endl;
continue;
}
else
{
a[i] = a[n];
cout << i << " " << n << endl;
continue;
}
}
}
return 0;
}