Codeforces Round #760 (Div. 3)
A. Polycarp and Sums of Subsequences
题目:——>传送门
题意:有一个长度为3的正整数数组a,将其中三个数中任选一个或两个或三个数组合,可以得到七个数字(七个数中有可能相同)组成数组b, 现在从小到大给你这七个数字,求最初的三个数是多少;
解题思路:由于数组a中都是正整数,那么b中最大的数字就是a中所有数字之和,倒数第二个数字和倒数第三个数字一定是a中两个数字相结合,倒数第四个数字则不一定,例如数组[1,2,10];
那么最后得到的三个数字就是b[7] - b[6],b[7] - b[5],b[7] - (b[7] - b[6]) - (b[7] - b[5]);
AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
void solve(){
int a[10];
for(int i = 1; i<=7; i++) scanf("%d", &a[i]);
int ans = a[7] - a[6];
int res = a[7] - a[5];
cout<<ans<<' '<<res<<' '<<a[7] - ans - res<<endl;
return;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}
B. Missing Bigram
题目:——>传送门
题意:定义一个长度为n的字符串可以被拆分成(n-1)个连续的长度为2的字符串称之为字,例如:“abbaaba” 可以被拆分成"ab", “bb”, “ba”, “aa”, “ab” 和 “ba”.现在小明按顺序给出拆分后的字,但是少了一个字,现在要求构造出一个字符串使得该字符串拆分的字和给出的(n-2)个字的相对顺序相同;
解题思路:直接通过给出的(n-2)个字去构造字符串,第一个字直接加入字符串中,对于后面的字,如果字的第一位和构造字符串的最后一位相同则只加上字的第二位,否则加上整个字;
AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
void solve(){
string c, s;
s = "";
int n;
scanf("%d", &n);
for(int i = 1; i<=n-2; i++){
cin>>c;
if(i == 1) {
s+=c;
continue;
}
if(c[0] == s[s.length()-1])s+=c[1];
else s+=c;
}
for(int i = s.length(); i<=n-1; i++) s+='a';
cout<<s<<endl;
return;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}
C. Paint the Array
题目:——>传送门
题意:给定一个正整数数组a,后把所有元素画成两种颜色。所有能被d整除的元素将被涂成红色,所有其他元素将被涂成蓝色。数组中没有相邻的元素具有相同的颜色, 即找到一个正整数d使得任意相邻的两数中一个能被d整除,一个不能被d整除,或者说不存在输出0;
解题思路:使得相邻的元素没有同样的颜色,则意味着要么从1开始每次每次加2染,要么从2开始每次加2染,首先一点要确定两组数据的最大公约数,然后再将一组数的最大公约数对另一组数便利,看能否整除,另一组同理;
AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 105;
ll a[N];
void solve(){
int n;
scanf("%d", &n);
for(int i = 1; i<=n; i++) scanf("%lld", &a[i]);
ll ans = a[1];
ll res = a[2];
for(int i = 1; i<=n; i+=2) ans = __gcd(ans, a[i]);
for(int i = 2; i<=n; i+=2) res = __gcd(res, a[i]);
int flag = 1;
for(int i = 2; i<=n; i+=2){
if(a[i]%ans == 0){
flag = 0;
break;
}
}
if(flag){
cout<<ans<<endl;
return;
}
for(int i = 1; i<=n; i+=2){
if(a[i]%res == 0){
puts("0");
return;
}
}
cout<<res<<endl;
return;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}
D. Array and Operations
题目:——>传送门
题意:给定一个数组长度为n的数组a,每次可以在数组中选择两个数x,y使得花费值加上x/y下取整,然后从数组中去掉x,y,该操作可以执行k次,保证2*k小于等于n;最后花费值加上剩余的数,求花费值最小的是多少;
解题思路:首先对于选择的数,因为是向下取整,则选择的两个数,大的数为分母,小的为分子,而为使得k次操作后花费的最少,则操作的数范围是将数组从小到大 排序后的[n-2k+1,n];将该段分为[n-2k+1,n-k)和[n-k+1,n],每次取两段中最大的数,若两数相等,则花费加一,否则花费不变;
AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 105;
int a[N];
void solve(){
int n, k;
scanf("%d%d", &n, &k);
for(int i = 1; i<=n; i++) scanf("%d", &a[i]);
sort(a+1, a+n+1);
int ans = 0;
int res = n-k*2+1;
for(int i = 1; i<res; i++){
ans+=a[i];
}
for(int i = res; i<=n-k; i++){
ans+=a[i]/a[k+i];
}
cout<<ans<<endl;
return;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}
E. Singers’ Tour
题目:——>传送门
题意:n个城镇按顺序排成一个圆,城镇编号1~n,每个城镇有一个音乐家,他们在自己城镇开演唱会花费a[i]的时间,然后会按顺序走访每一个城镇,每到下一个城镇演唱会时长就会多出a[i],现在给出各个城镇开演唱会的总时间数组b,求n个城镇的音乐家最开始演唱会的时间,即求数组a;如果无法求得数组a,则输出NO;
解题思路:题目有点像高中的数学公式应用题,根据题意可以知道,对于每一个b[i] = a[i]+2a[i-1]+3a[i-2]……na[i+1];那么所有的b[i]加起来后,每个a[i]的系数都是一样的即为1+2+3……+n可用公式n(n+1)/ 2表示,那么a1+a2+a3……+an的值就是所有的bi加起来除以n*(n+1)/ 2,设此值为S;
接下来,对于相邻的两个城镇:d[i]和d[i-1](i等于1的时候需要特判,下面的推到默认i不等于1);
d[i] = a[i] + 2a[i-1] + 3a[i-2] + ……+na[i+1];
d[i-1] = a[i-1] + 2a[i-2] + 3a[i-3] + …… + na[i];
令d[i]减去 d[i-1],错位相减,得到a[1]+a[2]+a[3]+……+na[i] = **S+na[i] = d[i] - d[i-1]**
上公式中只有a[i]一个未知数,可以直接求解,注意由于a中都是正整数当判断中出现无法整除的状态即无解;
AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 4e4+5;
ll a[N];
ll b[N];
void solve(){
int n;
scanf("%d", &n);
ll sum = 0;
for(int i = 1; i<=n; i++) scanf("%lld", &b[i]), sum+=b[i];
ll ans = n*(n+1)/2ll;
if(sum%ans!=0){
puts("NO");
return;
}
ans = sum/ans;
for(int i = 1; i<=n; i++){
int num = i-1;
if(num == 0) num = n;
ll res = (b[num] - b[i]+ans);
if(res%n!=0||res<=0){
puts("NO");
return;
}
a[i] = res/n;
}
puts("YES");
for(int i = 1; i<=n; i++) printf("%lld ", a[i]);
puts("");
return;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}