暑期Codeforces Round报告

Codeforces Round #730 (Div. 2)

A. Exciting Bets(补)

在这里插入图片描述

思路点拨

题意

max(gcd(a+n,b+n))以及偏移的距离n

思路

我们假设 a>=bgcd(x,0)=x (x>=0)

则有gcd(a,b)=gcd(a,a-b) 证明过程

因为无论如何操作,a-b都是固定不变的

所以max(gcd(a+n,b+n)) = max(gcd(a+n,a-b))

显然这个数为a-b

所以先特判,当a=b输出0 0

否则,我们只需要找到a-b的倍数中距离a较近的两个数s1 s2

n1=abs(s1-a)=a%(a-b)

n2=abs(s2-a)=a-b-a%(a-b)

所求的 n=min(n1,n2)

参考代码

// Problem: A. Exciting Bets
// Contest: Codeforces - Codeforces Round #730 (Div. 2)
// URL: https://codeforces.com/contest/1543/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
ll a,b,n;
int main()
{
	cin>>n;
	while(n--){
		cin>>a>>b;
		if(a==b){
			printf("0 0\n");continue;
		}
		if(a<b) swap(a,b);
		printf("%lld %lld\n",a-b,min(a%(a-b),a-b-a%(a-b)));
	}
}

B. Customising the Track

在这里插入图片描述

思路点拨

题意

给定一个数组a,你可以随意增减a[i]的值使得数组总和不变,前提是增减后的a[i]都非负,求 ∑ i = 1 n ∑ j = i + 1 n ∣ a i − a j ∣ \sum_{i=1}^{n}\sum_{j=i+1}^{n}{|a_i-a_j|} i=1nj=i+1naiaj的最小值

思路

设数组a的总和为 sum
平均数为 ave=sum/n,我们要让尽可能让更多的数接近平均数
那数组就会变成 sum%n个ave和 n-sum%nave+1的新数组
又会变成 sum%n 个0 和 n-sum%n1 的新数组
那结果就是 (n-sum%n)*(sum%n)

参考代码

// Problem: B. Customising the Track
// Contest: Codeforces - Codeforces Round #730 (Div. 2)
// URL: https://codeforces.com/contest/1543/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,n,a[200010],sum;
int main()
{
	cin>>t;
	while(t--){
		cin>>n;
		sum=0;
		for(int i=0;i<n;i++)
			cin>>a[i],sum+=a[i];
		printf("%lld\n",(n-sum%n)*(sum%n));
	}
}

Codeforces Round #731 (Div. 3)

A. Shortest Path with Obstacle

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

思路点拨

题意

给你ABF的坐标,其中F为陷阱,不能走

AB的最近距离

思路

不难发现规律:当ABF不在同一行且不在同一列时,FAB最短距离无影响

ABF在同一行或同一列时,只要在最短距离的基础上绕过F(+2)即可

参考代码

// Problem: A. Shortest Path with Obstacle
// Contest: Codeforces - Codeforces Round #731 (Div. 3)
// URL: https://codeforces.com/contest/1547/problem/A
// Memory Limit: 512 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
int t,a1,a2,b1,b2,f1,f2;
int main()
{
	cin>>t;
	while(t--){
		cin>>a1>>a2>>b1>>b2>>f1>>f2;
		if(a1==b1&&f1==a1){
			if((f2>a2&&f2<b2)||(f2>b2&&f2<a2)) cout<<abs(a1-b1)+abs(a2-b2)+2<<endl;
			else cout<<abs(a1-b1)+abs(a2-b2)<<endl;
		}
		else if(f2==a2&&a2==b2){
			if((f1>a1&&f1<b1)||(f1>b1&&f1<a1))	cout<<abs(a1-b1)+abs(a2-b2)+2<<endl;
			else cout<<abs(a1-b1)+abs(a2-b2)<<endl;
		}	
		else cout<<abs(a1-b1)+abs(a2-b2)<<endl;
	}
}

B. Alphabetical Strings

在这里插入图片描述

思路点拨

题意

S是空字符串,我们可以在S的开头或结尾按字母表顺序添加若干字母形成新S,再在新S的基础上重复上述操作。
现在给出若干字符串,判断字符串是否满足上述规则。

思路

根据题意模拟判断即可

参考代码

// Problem: B. Alphabetical Strings
// Contest: Codeforces - Codeforces Round #731 (Div. 3)
// URL: https://codeforces.com/contest/1547/problem/B
// Memory Limit: 512 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
int n;
string s;
bool isa(string &s){
	int len=s.length(),o;
	char c='a';
	if(s.find(c)!=string::npos) o=s.find(c);
	else return false;
	int p=o-1,q=o+1;
	c=(char)c+1;
	for(;p>=0||q<len;p--,q++){
		if(p>=0&&s[p]==c){
			c=(char)c+1;
			q--;
		}
		else if(q<len&&s[q]==c){
			c=(char)c+1;
			p++;
		}
		else return false;
	}
	return true;
}
int main()
{
	cin>>n;
	while(n--){
		cin>>s;
		if(isa(s)) puts("YES");
		else puts("NO");
	}
}

C. Pair Programming

在这里插入图片描述
在这里插入图片描述

思路点拨

题意

第一行给你三个数kab

k表示初始的文件行数

ab表示M和P一共工作了a+b分钟

第二行是序列1的操作,从a[1],a[2],a[3],...a[n],当a[i]=0,那么M在文件的最后一行添加一行,当a[i]>0,那么M将修改第a[i]行,前提是文件行数>=a[i],否则就是非法操作

第三行是序列2的操作,从b1,b2,b3,...bn,操作过程同上

MP分别只能按照a[1]-a[n]b[1]-b[n]的顺序执行操作,但是MP可以任意交替操作,比如a[1],b[1],a[2],a[3],b[2]

对于每个测试用例,如果有合法操作的话则输出长度为n+m的合法操作,否则输出-1

思路

思路:利用双指针同时左往右遍历,在未越界的前提下,贪心地优先在文件末尾添加新行,其次寻找两个当中的较小的,判断较小的是否合法。

参考代码

// Problem: C. Pair Programming
// Contest: Codeforces - Codeforces Round #731 (Div. 3)
// URL: https://codeforces.com/contest/1547/problem/C
// Memory Limit: 512 MB
// Time Limit: 2000 ms
 
#include<bits/stdc++.h>
using namespace std;
int t,k,n,m,sum,nummax;
int a[110],b[110],c[220];
int posc;
bool istrue(){
	int posa=0,posb=0;posc=0;
	for(;posa<n||posb<m;){
		if(posa<n&&posb<m){
			if(!a[posa]) c[posc++]=0,posa++,k++;
			else if(!b[posb]) c[posc++]=0,posb++,k++;
			else if(min(a[posa],b[posb])>k) return false;
			else if(a[posa]<=b[posb]) c[posc++]=a[posa++];
			else c[posc++]=b[posb++];
		}
		else if(posa<n){
			if(!a[posa]) c[posc++]=0,posa++,k++;
			else if(a[posa]>k) return false;
			else c[posc++]=a[posa++];
		}
		else if(posb<m){
			if(!b[posb]) c[posc++]=0,posb++,k++;
			else if(b[posb]>k) return false;
			else c[posc++]=b[posb++];
		}
	}
	return true;
}
int main()
{
	cin>>t;
	while(t--){
		cin>>k>>n>>m;
		sum=0,nummax=0;
		for(int i=0;i<n;i++){
			cin>>a[i];
			if(!a[i]) sum++;
			nummax=max(a[i],nummax);
		}
		for(int i=0;i<m;i++){
			cin>>b[i];
			if(!b[i]) sum++;
			nummax=max(b[i],nummax);
		}
		if(k+sum<nummax) puts("-1");
		else{
			if(istrue()){
				printf("%d",c[0]);
				for(int i=1;i<posc;i++)
					printf(" %d",c[i]);
				puts("");
			}
			else puts("-1");
		}
	}
}

Educational Codeforces Round 111 (Rated for Div. 2)

A. Find The Array

在这里插入图片描述

思路点拨

题意

对于数组a,如果对于从 1n 的每个 i 都满足a[i]=1,或者至少存在数字a[i]-1a[i]-2在数组a中,则称数组 a 是美丽的。

现给你t个数,对于每个正整数s,找到数组各元素总和等于 s 的美丽数组的最小长度

思路

如果美丽数组升序排列,则有如下规律
[a1,a2,a3,a4,a5......]
要么 a1=a2=a3=a4=a5=......=1
要么a1=1,a2∈[2,3],a3∈[4,5],a4∈[6,7],a5∈[8,9]......
因为我们要找出最小长度,所以优先选择第二种

则其前缀和s ( ( n − 1 ) ∗ ( n − 1 ) , n ∗ n ] ((n-1)*(n-1),n*n] ((n1)(n1),nn]
答案则为 n
当时比赛看数据范围不大,就直接暴力了

参考代码

// Problem: A. Find The Array
// Contest: Codeforces - Educational Codeforces Round 111 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1550/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
 
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n;
int main()
{
	IOS;cin>>t;
	while(t--){
		cin>>n;
		int sum=0,k=0;
		for(int i=1;sum<n;i+=2){
			sum+=i;
			k++;
		}
		printf("%d\n",k);
	}
}

B. Maximum Cost Deletion

在这里插入图片描述

思路点拨

题意

给定一个长度为n的字符串s,它只包含字符01
您执行以下操作,直到字符串变空:选择一些连续的相同字符的子字符串,将其从字符串s中删除,然后将剩余的两部分连接在一起。
例如,如果从字符串111110中删除子字符串111,您将得到字符串110。当您删除长度为l的子字符串时,您将得到a*l+b点分数。
如果您必须将给定的字符串全部删除,您的任务是计算您总共可以获得的最大分数。
输入一个整数t代表测试用例的数量
每个测试用例的第一行包含字符串s的长度n以及参数ab
第二行包含字符串s。字符串s仅由字符01组成
对于每个测试用例,输出您可以得分的最大点数

思路

我们不难发现,随着删除次数的增加,字符串s总会被完全删除,所以 ∑ a ∗ l \sum a*l al其实就是a*n
所以关键就在b
b>0时,b对结果的贡献是正向的,所以我们就尽量增加删除次数,让b多做贡献,也就是一次只删除一个字符,最后结果就是 ∑ a ∗ l + b = a ∗ n + b ∗ n = ( a + b ) ∗ n \sum a*l+b = a*n+b*n =(a+b)*n al+b=an+bn=(a+b)n
b=0时,对结果无影响
b<0时,对结果的贡献是反向的,所以我们就尽量减少删除次数,
这里我们用 num记录相邻不同字符的个数,得出如下规律

num最少删除次数
01
12
22
33
43
54
64
75
85
96
num>0(num+1)/2+1

也就是当 n u m = 0 num=0 num=0,结果就是 ∑ a ∗ l + b = a ∗ n + b \sum a*l+b = a*n+b al+b=an+b

n u m > 0 num>0 num>0,结果就是 ∑ a ∗ l + b = a ∗ n + ( ( n u m + 1 ) / 2 + 1 ) ∗ b \sum a*l+b = a*n+((num+1)/2+1)*b al+b=an+((num+1)/2+1)b

参考代码

// Problem: B. Maximum Cost Deletion
// Contest: Codeforces - Educational Codeforces Round 111 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1550/problem/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n,a,b;
string s;
int main()
{
	IOS;cin>>t;
	while(t--){
		cin>>n>>a>>b>>s;
		int num=0;
		for(int i=1;s[i];i++)
			if(s[i]!=s[i-1]) num++;
		if(!num) num++;
		else num=(num+1)/2+1;
		if(b>=0) printf("%d",(a+b)*n);
		else printf("%d",a*n+num*b);
		puts("");
	}
}

Codeforces Round #734 (Div. 3)

A. Polycarp and Coins

在这里插入图片描述

思路点拨

题意

你需要付款 n(n>0)
但你只有两个面值的硬币:1元和2
你需要支付c11元硬币和c22元硬币使得支付总面值为n元 即(c1+2*c2=n)
此外,你必须要使得|c1-c2|尽可能小
给定多个n,对于每个n输出对应的c1c2

思路

n%3==0时, c 1 = c 2 = n / 3 c1=c2=n/3 c1=c2=n/3
n%3!=0时, c 1 = n − ( n + 1 ) / 3 ∗ 2 c1=n-(n+1)/3*2 c1=n(n+1)/32 c 2 = ( n + 1 ) / 3 c2=(n+1)/3 c2=(n+1)/3
我们发现第一种情况也满足第二种情况

nc1(1)c2(2)
110
201
311
421
512
622
732
823
933
1043

参考代码

// Problem: A. Polycarp and Coins
// Contest: Codeforces - Codeforces Round #734 (Div. 3)
// URL: https://codeforces.com/contest/1551/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n;
int main()
{
	cin>>t;
	while(t--){
		cin>>n;
		printf("%d %d\n",n-(n+1)/3*2,(n+1)/3);
	}
}

B1. Wonderful Coloring - 1

在这里插入图片描述

思路点拨

题意

PaulMary有一个最喜欢的字符串s,它由小写字母组成。他们想用两种颜色的粉笔来画它:红色绿色。如果满足以下条件,让我们将字符串的着色称为美妙的:

  1. 字符串的每个字母要么只涂上一种颜色(红色或绿色),要么不涂
  2. 涂上相同颜色的两个字母各不相同
  3. 红色字母的数量等于绿色字母的数量;
  4. 在满足前三个条件的字符串的所有颜色中,该颜色的涂色字母数量最多

输入t个测试用例
每个测试用例由一个非空字符串s组成,该字符串小写字母组成。字符串中的字符数不超过50
对于每个测试用例,输出将被涂成红色并呈现美妙色彩的字母数。

思路

根据题意我们可知:
规则3可得:如果该字母出现次数≥2的话,我们只选择其中两个字母分别涂上红色和绿色,剩余的不涂。如果该字母仅出现一次的话,我们也暂时先选择不涂。
由规则4可得:我们可以在前面的基础上,对只出现过一次的字母(刚刚暂时先不涂的字母)任意两两配对,分别涂上红色和绿色,这样可以使得涂色字母数量最多。

参考代码

// Problem: B1. Wonderful Coloring - 1
// Contest: Codeforces - Codeforces Round #734 (Div. 3)
// URL: https://codeforces.com/contest/1551/problem/B1
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t;
string s;
int main()
{
	IOS;
	cin>>t;
	while(t--){
		int a[30]={0};
		int num1=0,num2=0;
		cin>>s;
		for(int i=0;s[i];i++)
			a[s[i]-'a']++;
		for(int i=0;i<26;i++)
			if(a[i]==1) num1++;
			else if(a[i]>=2) num2++;
		cout<<num1/2+num2<<endl;
	}
}

B2. Wonderful Coloring - 2(补)

在这里插入图片描述
在这里插入图片描述

思路点拨

题意

最近,PaulMary发现了一个新的最喜欢的整数序列 a[1],a[2],...,a[n]。他们想用k种颜色的粉笔来画它。如果满足以下条件,则序列的着色称为美妙

  1. 序列的每个元素要么用k种颜色之一绘制,要么不绘制;
  2. 没有两个相同的值以相同颜色绘制;
  3. k种颜色中的每一种所绘制的元素数量必须相等;
  4. 序列的着色元素总数是满足前三个条件的序列所有着色中的最大值。

序列a=[3,1,1,1,1,10,3,10,10,2]k=3美妙着色示例。请注意,其中一个元素没有被绘制。
帮助PaulMary找出给定序列a美妙着色

输入t个测试用例。
每个测试用例由两行组成。
第一个包含两个整数nk ( 1 ≤ n ≤ 2 E 5 , 1 ≤ k ≤ n ) (1≤n≤2E5, 1≤k≤n) (1n2E5,1kn)分别是序列的长度颜色数
第二个包含 n 个整数a[1],a[2],...,a[n] ( 1 ≤ a i ≤ n ) (1≤ai≤n) (1ain) 表示该序列。
保证所有测试用例的n总和不超过2E5

输出t行,每行都必须包含对相应测试用例的精彩着色的描述。
每个美妙的颜色都必须打印为由空格分隔的n整数c[1],c[2],…,c[n] ( 0 ≤ c i ≤ k ) (0≤ci≤k) (0cik)的序列,其中
ci=0,如果第i个元素没有被绘制;
ci>0,如果第i个元素以第ci颜色绘制。
请记住,您需要最大化绘制元素的总数以获得美妙的色彩。如果有多种解决方案,请打印任何一种。

思路

我们现将原序列记录下来,再将原序列按照数值排序,对于出现次数>k的元素进行标记,遍历整个序列后统计出未被标记的元素个数num
因为我们要保证各种颜色的个数统一,所以当 n u m % k = = 0 num\%k==0 num%k==0时,我们直接按照顺序进行填充即可。当 n u m % k ! = 0 num\%k!=0 num%k!=0时,我们将前 n u m % k num\%k num%k个元素进行标记,然后将剩余元素按照顺序填充即可。
最后输出的时候记得先恢复原序列顺序哦!

参考代码

// Problem: B2. Wonderful Coloring - 2
// Contest: Codeforces - Codeforces Round #734 (Div. 3)
// URL: https://codeforces.com/contest/1551/problem/B2
// Memory Limit: 256 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n,k,p,num;
struct node{
	int s,pos,num;
}a[200100];
bool cmp1(node a,node b){
	return a.s<b.s;
}
bool cmp2(node a,node b){
	return a.num<b.num;
}
int main()
{
	IOS;
	cin>>t;
	while(t--){
		cin>>n>>k;
		p=1,num=n;
		for(int i=0;i<n;i++){
			cin>>a[i].s;
			a[i].num=i;
		}
		sort(a,a+n,cmp1);
		a[0].pos=1;
		for(int i=0;i<n;i++){
			if(i){
				if(a[i].s==a[i-1].s) p++;
				else p=1;
				if(p>k) a[i].pos=-1,--num;
				else a[i].pos=0;
			}
			//cout<<a[i].s<<" "<<a[i].pos<<endl;
		}
		for(int i=1;i<=num%k;i++)
			a[i].pos=-1;
		if(k-1) p=1;
		else p=0;
		for(int i=num%k+1;i<n;i++){
			if(a[i].pos+1) a[i].pos=++p;
			if(p==k) p=0;
		}
		sort(a,a+n,cmp2);
		for(int i=0;i<n;i++){
			if(i) cout<<" ";
			if(a[i].pos+1) cout<<a[i].pos;
			else cout<<"0";
		}
		cout<<endl;
	}
}

C. Interesting Story(补)

在这里插入图片描述

思路点拨

题意

在每个测试样例中会给你一些字符串,每个字符串中只包含字母a-e,你要在其中尽可能多地挑选并组合成一个新的字符串,使得得到的新字符串中某个字母出现的次数其余字母出现的次数总和多,统计组成新字符串的旧字符串个数

思路

枚举每个字符串中a-e各个字母的贡献,sort之后贪心,直到贡献非正。

参考代码

// Problem: C. Interesting Story
// Contest: Codeforces - Codeforces Round #734 (Div. 3)
// URL: https://codeforces.com/contest/1551/problem/C
// Memory Limit: 256 MB
// Time Limit: 4000 ms
 
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n;
struct node{
	string k;
	int pos[5];
}s[200100];
int p[5][200100];
int main()
{
	cin>>t;
	while(t--){
		int a[5]={0};
		cin>>n;
		for(int i=0;i<n;i++){
			cin>>s[i].k;
			for(int j=0;s[i].k[j];j++)
				a[s[i].k[j]-'a']++;
		}
		for(int k=0;k<5;k++){
			char c=k+'a';
			for(int i=0;i<n;i++){
				int num=0;
				for(int j=0;s[i].k[j];j++)
					if(s[i].k[j]==c) num++;
				s[i].pos[k]=num*2-s[i].k.length();
  //计算第i个字符串中第k个字母的贡献
  //这里把 num-(s[i].k.length()-num) 写成了 num*2-s[i].k.length();
			}
		}
		for(int i=0;i<5;i++)
			for(int j=0;j<n;j++)
				p[i][j]=s[j].pos[i];
	//p[i][j] 代表 第i个字母在第j个字符串中的贡献
	//贪心
		int maxx=0;
		for(int i=0;i<5;i++){
			sort(p[i],p[i]+n,greater<int>());
			int num=0,sum=0;
			for(int j=0;j<n;j++){
				sum+=p[i][j];
				if(sum>0) num++;
				else break;
			}
			maxx=max(maxx,num);
		}
		cout<<maxx<<endl;
	}
}

Codeforces Global Round 15

A. Subsequence Permutation

在这里插入图片描述

思路点拨

题意

给你一个长度为n的字符串s,你可以选择k个字母保持不动,改变剩余字母的排序,使得得到的新字符串是按字典序升序,问k是多少

思路

sort后遍历统计即可

参考代码

// Problem: A. Subsequence Permutation
// Contest: Codeforces - Codeforces Global Round 15
// URL: https://codeforces.com/contest/1552/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n,num;
string s;
int main()
{
	cin>>t;
	while(t--){
		cin>>n>>s;
		string k=s;
		num=0;
		sort(s.begin(),s.end());
		for(int i=0;s[i];i++)
			if(s[i]!=k[i]) num++;
		printf("%d\n",num);
	}
}

Codeforces Round #735 (Div. 2)

A. Cherry

在这里插入图片描述

思路点拨

题意

给你n个数,下标记作[1,n]F(L,R)定义为区间[L,R]中最大的数和最小的数的乘积,让你找出最大的F(L,R)是多少

思路

假如有这么一组数
a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8]
假如当我们选择L=2,R=6时,假如最大值是a[5],最小值是a[3]
F(2,6) = a[5] * a[3],那既然a[3]L=2,R=6中最小的数,那我们应该选择L=4,R=6,这样的话最大值还是a[5],但最小值一定会大于等于a[3],即F(4,6)≥F(2,6),以此类推我们发现当max和min不相邻的时候,就一定能够找出更优解,所以只要枚举相邻两数乘积,输出最大值即可。

参考代码

// Problem: A. Cherry
// Contest: Codeforces - Codeforces Round #735 (Div. 2)
// URL: https://codeforces.com/contest/1554/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
ll t,n,maxx;
ll a[1000000];
int main()
{
	IOS;cin>>t;
	while(t--){
		cin>>n>>a[0];
		maxx=a[0];
		for(ll i=1;i<n;i++){
			cin>>a[i];
			maxx=max(maxx,a[i]*a[i-1]);
		}
		cout<<maxx<<endl;
	}
}

Educational Codeforces Round 112 (Rated for Div. 2)

A. PizzaForces(补)

在这里插入图片描述

思路点拨

题意

有小中大三种尺寸的披萨,小披萨6片组成,中披萨8片组成,大披萨10片组成,制作时间分别是152025分钟。
每次有n位朋友来参加聚会,你需要准备n片披萨,请你求出制作至少包含n片披萨所需的最小分钟数

思路

可以算出平均时间都是每2.5分钟做好一片披萨,但当n奇数时是没办法凑出来的,只能多做一片,特判一下n<6的时候即可

参考代码

// Problem: A. PizzaForces
// Contest: Codeforces - Educational Codeforces Round 112 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1555/problem/A
// Memory Limit: 256 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
ll t,n;
int main()
{
	cin>>t;
	while(t--){
		cin>>n;
		if(n&1) n++;
		if(n<6) n=6;
		cout<<n*2+n/2<<endl;
	}
}

B. Two Tables(补)

在这里插入图片描述

思路点拨

题意

有一个与轴对齐的矩形房间,宽度为W,高度为H
左下角在(0,0),右上角在(W,H)
这个房间里有一张长方形的桌子,桌子的侧面与墙壁平行
左下角位于(x1,y1),右上角位于(x2,y2)
您希望在此房间中放置另一张矩形桌子,宽度为w,高度为h
桌子的宽度与房间的宽度平行。
问题是有时没有足够的空间来放置第二个桌子而不与第一个桌子相交(尽管桌子接触没有问题)
您不能旋转任何桌子,但可以在房间内移动第一张桌子。
为了给第二张桌子腾出足够的空间,移动第一张桌子的最小距离是多少?

思路

计算两个桌子的总宽和总高,与房间的宽高比较,看看能否放得下
放得下的话则验证不移动能否放得下
否则左右能放则取最小值maxx1,上下能放则取最小值maxx2,答案即min(maxx1,maxx2)

参考代码

// Problem: B. Two Tables
// Contest: Codeforces - Educational Codeforces Round 112 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1555/problem/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t;
int w,h,x1,y1,x2,y2,ww,hh;
int main()
{
	cin>>t;
	while(t--){
		cin>>w>>h>>x1>>y1>>x2>>y2>>ww>>hh;
		if(ww-x1+x2>w&&hh-y1+y2>h) puts("-1");
		else if(y1>=hh||x1>=ww||w-x2>=ww||h-y2>=hh) puts("0.000000000");
		else{
			double maxx1=INT_MAX,maxx2=INT_MAX;
			if(ww-x1+x2<=w) maxx1=min(abs(x1-ww),abs(x2-(w-ww)));
			if(hh-y1+y2<=h) maxx2=min(abs(y1-hh),abs(y2-(h-hh)));
			printf("%.9lf\n",min(maxx1,maxx2));
		}
	}
}

C. Coin Rows(补)

在这里插入图片描述

思路点拨

题意

该矩阵由2行,m列组成
i行第j列的单元格中包含a[i][j]硬币
起初A和B都在(1,1)处,每次移动,他们可以向或向走,直到走到(2,m)
A先走,B后走
游戏的分数是B收集的硬币总数。
A想把分数降到最低,B想把分数尽可能提高,他们都绝对聪明

思路

因为两人绝对聪明,A只能往下走一次,当A从第k格往下走的时候,B的分数就是max( ∑ s = k + 1 n a [ 1 ] [ s ] ∑^n_{s=k+1}a[1][s] s=k+1na[1][s], ∑ s = 1 k − 1 a [ 1 ] [ s ] ∑^{k-1}_{s=1}a[1][s] s=1k1a[1][s]),所以预处理一下遍历即可。

参考代码

// Problem: C. Coin Rows
// Contest: Codeforces - Educational Codeforces Round 112 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1555/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n;
int a[3][100100];
int main()
{
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=2;i++)
			for(int j=1;j<=n;j++)
				cin>>a[i][j];
		if(n==1){
			puts("0");
			continue;
		}
		for(int i=n-1;i>=1;i--)
			a[1][i]+=a[1][i+1];
		for(int i=2;i<=n;i++)
			a[2][i]+=a[2][i-1];
		int minn=INT_MAX;a[1][n+1]=0,a[2][0]=0;
		for(int i=1;i<=n;i++)
			minn=min(minn,max(a[1][i+1],a[2][i-1]));
		cout<<minn<<endl;
	}
}

Codeforces Round #736 (Div. 2)

A. Gregor and Cryptography

在这里插入图片描述

思路点拨

题意

给你素数P。两个整数ab使得 P % a = P % b P\%a=P\%b P%a=P%b

思路

P是素数,肯定是奇数,所以 P % 2 = 1 P\%2=1 P%2=1,要使得 P % b = 1 P\%b=1 P%b=1,很显然 b = P − 1 b=P-1 b=P1

参考代码

// Problem: A. Gregor and Cryptography
// Contest: Codeforces - Codeforces Round #736 (Div. 2)
// URL: https://codeforces.com/contest/1549/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n;
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		cout<<2<<" "<<n-1<<endl;
	}
}

B. Gregor and the Pawn Game在这里插入图片描述

思路点拨

题意

有一个大小为n*n的棋盘。
G在第n排有一些棋子。第1排有敌人的棋子
在一个回合中,G移动了他的一个棋子
如果那颗棋子上方没有棋子的话,G可以向上移动棋子 ( 从 [ i , j ] 到 [ i − 1 , j ] ) (从[i,j]到[i-1,j]) ([i,j][i1,j])
否则,当且仅当该方格中有敌方棋子时,G的棋子可以沿对角线向左上或右上移动, ( 从 [ i , j ] 到 [ i − 1 , j − 1 ] 或 [ i − 1 , j + 1 ] ) (从[i,j]到[i−1,j−1]或[i−1,j+1]) ([i,j][i1,j1][i1,j+1])。移动后该位置上敌人的棋子将被移除。
G想知道他能到达第一排的最大棋子数是多少?
请注意,在这个游戏中只有G的棋子在移动,而敌方的棋子从不移动
此外,当G的棋子到达第一排时,它就不能再移动了。

思路

模拟即可

参考代码

// Problem: B. Gregor and the Pawn Game
// Contest: Codeforces - Codeforces Round #736 (Div. 2)
// URL: https://codeforces.com/contest/1549/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n;
int a[2][200100];
int main()
{
	cin>>t;
	while(t--){
		scanf("%d",&n);getchar();
		for(int i=0;i<=1;i++){
			for(int j=0;j<n;j++)
				a[i][j]=getchar()-'0';
			getchar();
		}
		int num=0;
		for(int i=0;i<n;i++){
			if(a[1][i]){
				if(!a[0][i]) num++;
				else if(i-1>=0&&a[0][i-1]) a[0][i-1]=0,num++;
				else if(i+1<n&&a[0][i+1]) a[0][i+1]=0,num++;
			}
		}
		printf("%d\n",num);
	}
}

Codeforces Round #737 (Div. 2)

A. Ezzat and Two Subsequences

在这里插入图片描述

思路点拨

题意

给你一组数,请你把它们成两组,计算每组的平均数,使得两组的平均数的和最大

思路

最大的一个数单独一组,剩下的数一组

最大的数除以1,其他的除以(n-1)

参考代码

// Problem: A. Ezzat and Two Subsequences
// Contest: Codeforces - Codeforces Round #737 (Div. 2)
// URL: https://codeforces.com/contest/1557/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
/
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n;
int a[100100];
int main()
{
	cin>>t;
	while(t--){
		double sum=0;int maxx=INT_MIN;
		cin>>n;
		for(int i=0;i<n;i++){
			cin>>a[i];
			maxx=max(maxx,a[i]);
			sum+=a[i];
		}
		sum-=maxx;
		printf("%.10lf\n",sum/(n-1)+maxx);
	}
}

B. 离散化的题待补(补)

在这里插入图片描述

思路点拨

题意
思路

参考代码

Codeforces Round #738 (Div. 2)

A. Mocha and Math

在这里插入图片描述

思路点拨

题意

有一个长度为n的数组a,在每次操作中,她可以选择任意的区间[L,R],用a[L+i]&a[R−i]替换a[L+i],其中0≤i≤R−L&表示按位与运算。 此操作可以执行任意次,能否使操作后的数组中的最大值最小,求操作后数组中的最大值是多少?

思路

根据按位与的性质,有00,全11,两个数ab按位与之后的结果是c,那么c≤max(a,b),那么直接遍历异或即可

参考代码

// Problem: A. Mocha and Math
// Contest: Codeforces - Codeforces Round #738 (Div. 2)
// URL: https://codeforces.com/contest/1559/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n;
int a[110];
int main()
{
	cin>>t;
	while(t--){
		cin>>n>>a[0];
		for(int i=1;i<n;i++){
			cin>>a[i];
			a[0]&=a[i];
		}
		cout<<a[0]<<endl;
	}
}

B. Mocha and Red and Blue

在这里插入图片描述

思路点拨

题意

给你一个由BR? 构成的字符串,B代表蓝色,R代表红色,?代表空白。
我们把相邻的具有相同的颜色的方块称作不完美,例如BBRR
现在你可以选择在空白处涂上蓝色红色,使得最后得到的字符串的不完美的个数最少,输出涂色后的字符串

思路

首先统计字符串中?的个数
如果全是?的话则先把第一个随意涂色
特判字符串长度为1的时候,把?随意涂色之后输出
从头至尾遍历,对于形如B?R?,涂色成BRRB
从尾至头遍历,对于形如?B?R,涂色成RBBR

参考代码

// Problem: B. Mocha and Red and Blue
// Contest: Codeforces - Codeforces Round #738 (Div. 2)
// URL: https://codeforces.com/contest/1559/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)

int t,n,len,num;
string s;
int main()
{
	cin>>t;
	while(t--){
		cin>>len>>s;
		num=0;
		for(int i=0;s[i];i++)
			num+=s[i]!='?';
		if(!num) s[0]='B';
		if(s.length()==1&&s[0]=='?') cout<<'B'<<endl;
		else{
			for(int i=0;s[i];i++)
				if(!i) continue;
				else if(s[i]=='?'&&s[i-1]!='?') s[i]=s[i-1]^('B'^'R');
			for(int i=s.length()-1;i>=0;i--)
				if(i==s.length()-1) continue;
				else if(s[i]=='?'&&s[i+1]!='?') s[i]=s[i+1]^('B'^'R');
			cout<<s<<endl;
		}
	}
}

C. Mocha and Hiking(补)

在这里插入图片描述

思路点拨

题意

给你一个数字n,表示有n+1个村庄和2n-1条路
对于[1,n-1]的村庄都有一条有向路通向下一个村庄
下一行有一个由n个数字组成的数组a
a[i]=0时,表示村庄i到村庄n+1有一条有向路
a[i]=1时,表示村庄n+1到村庄i有一条有向路
请你找出一条路径,使得你能从任意起点开始走完所有村庄,找不到输出-1

思路

首先判断从nn+1是否有路,有路则直接输出[1,n+1]
其次判断从n+11是否有路,有路则先输出n+1,再输出[1,n]
最后判断是否有形如a[i]==0&&a[i+1]==1,有的话则表示能从i走到n+1后还能回到i+1,则输出[1,i],n+1,[i+1,n]
不满足上述要求则无解

参考代码

// Problem: C. Mocha and Hiking
// Contest: Codeforces - Codeforces Round #738 (Div. 2)
// URL: https://codeforces.com/contest/1559/problem/C
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n,a[10100];
int main()
{
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++)
			cin>>a[i];
		if(!a[n]){
			for(int i=1;i<=n;i++)
				cout<<i<<" ";
			cout<<n+1<<endl;
		}
		else if(a[1]){
			cout<<n+1<<" ";
			for(int i=1;i<n;i++)
				cout<<i<<" ";
			cout<<n<<endl;
		}
		else{
			bool f=true;
			for(int i=1;i<n&&f;i++)
				if(!a[i]&&a[i+1]){
					cout<<"1";
					for(int j=2;j<=i;j++)
						cout<<" "<<j;
					cout<<" "<<n+1;
					for(int j=i+1;j<=n;j++)
						cout<<" "<<j;
					cout<<endl;
					f=false;
				}
			if(f) puts("-1");
		}
	}
}

Codeforces Round #739 (Div. 3)

A. Dislike of Threes

在这里插入图片描述

思路点拨

题意

有一个数组,从1开始,不包括以3结尾的数字和3的倍数
输入一个数k,输出数组中第k个数字

思路

预处理打表输出即可

参考代码

// Problem: A. Dislike of Threes
// Contest: Codeforces - Codeforces Round #739 (Div. 3)
// URL: https://codeforces.com/contest/1560/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
int t,n,pos;
int a[1100];
int main()
{
	for(int i=0;pos<1100;i++)
		if(i%3==0||i%10==3) continue;
		else a[pos++]=i;
	cin>>t;
	while(t--){
		cin>>n;
		cout<<a[n-1]<<endl;
	}
}

B. Who’s Opposite?

在这里插入图片描述

思路点拨

题意

有若干个人站成一圈。人们均匀地站在圆圈里。它们从编号为1的人开始顺时针编号。每个人都通过圆圈的中心看对面的人。给你三个数abc,即a对面是b,求c的对面是谁?

思路

规律1:我们假设a>b,那么对立着的两人的差是固定不变的,都是a-b。所以跟c对立的编号是c+(a-b)c-(a-b)
规律2:最小的编号是1,最大的编号是(a-b)*2
接下来只要判断这两个编号ab是否合法并且这三个不重复即可

参考代码

// Problem: B. Who's Opposite?
// Contest: Codeforces - Codeforces Round #739 (Div. 3)
// URL: https://codeforces.com/contest/1560/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
LL t,a,b,c,n;
int main()
{
	cin>>t;
	while(t--){
		cin>>a>>b>>c;
		if(a<b) swap(a,b);
		LL eps=a-b,maxx=(a-b)*2;
		LL c1=c+eps,c2=c-eps;
		if(c>maxx||maxx<a||maxx<b) puts("-1");
		else if(c1<=maxx&&c1!=a&&c1!=b) cout<<c1<<endl;
		else if(c2>0&&c2!=a&&c2!=b) cout<<c2<<endl;
		else puts("-1");
	}
}

C. Infinity Table

在这里插入图片描述

思路点拨

题意

根据题目中的图示填数,给你一个数n,输出在第几行第几列

思路

i行第i列上的数字是i*(i-1)+1
第一列的数字都是平方数,所以平方数都在第sqrt(n)行,第1
其次判断n是否在第sqrt(n)+1行上,即n是否在[ (sqrt(n)+1)*sqrt(n)+1 , (sqrt(n)+1 )*(sqrt(n)+1) ]
否则n就一定在第sqrt(n)+1列上,再根据(sqrt(n)+1)*sqrt(n)+1的差来判断在第几行上

参考代码

// Problem: C. Infinity Table
// Contest: Codeforces - Codeforces Round #739 (Div. 3)
// URL: https://codeforces.com/contest/1560/problem/C
// Memory Limit: 256 MB
// Time Limit: 1000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
LL t,n;
int main()
{
	cin>>t;
	while(t--){
		cin>>n;
		LL xx,yy,kk,tp=sqrt(n);
		if(n==tp*tp) xx=tp,yy=1;
		else {
			xx=tp+1,yy=1,kk=(tp+1)*(tp+1);
			if(n>=(kk-xx+1)) yy=kk-n+1;
			else{
				yy=xx;
				kk=kk-xx+1;
				xx=xx-(kk-n);
			}
		}
		cout<<xx<<" "<<yy<<endl;
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值