Codeforces Round #629 (Div. 3)(A-D)

A 取模运算就行。

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int main()
{
	ll t,n,m;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		cout<<(m-n%m)%m<<endl;//n%m=0时需要输出0,再取模一次就可以了
	}
	return 0;
}

B 求第k个全排列,数据范围太大直接全排列会超时的,这个字符串有些特殊,是可以找规律了,已知两个b的位置分别是n-1,n-2,每次全排列是先移动第一个b,然后移动第二个b,当两个相邻后,第一个b想右移动,第二个b回位置n,然后再继续移动第二个b,知道两个b相邻再重复前面的。
所以可以找到,第一个b移动0次的最小k是1,第一个b移动1次的最小k是2,移动三次的最小k是4…有了这个规律就可以确定第一个b移动几次就可以确定它的位置,然后第二个b最多不会超多第一个的次数所以减一下就是了,这样两个b的位置定了剩下就全是b了,还需要特判一下如果第一个b溢出了就输出字典序最大的串(bbaa…)就行了

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll  a[200010];
void init()//预处理,我算的是最小步数减1,所以后边查找m-1
{
	a[1]=1;
	for(int i=1;i<=100000;i++)
		a[i]=a[i-1]+i;
	return ;
}
int main()
{
	init();
	ll t,n,m;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		int l=upper_bound(a,a+100000,m-1)-a,r;//
		l--;//找到的是第一个大于m-1的位置,所以减1才是第一个b的位置
		r=m-1-a[l];//l,r是左移的位数
		if(l>=n-1) //特判b溢出
		{
			cout<<"bb";
			for(int i=1;i<=n-2;i++) cout<<'a';
		}
		else 
		{
			for(int i=1;i<=n;i++)
				if(i+l==n-1||i+r==n) cout<<'b';
				else cout<<'a';
		}
			cout<<endl;
	}
	return 0;
}

C 找到满足它的规则并且最大值尽量小的值,就是尽量平分那个值。
0,2都是可以平分的,只有1不是,假设我们分为两个值a,b。从高位向低位遍历,0和2是可以平分的不用管,直到第一个的1的位置,只能分为0和1假设a的只以为分为1,b的这一位分为0,那么不管不管后面再怎么分a一定大于b,那么后面就要在和为s(已知的那个数)的情况下使a尽量小,那么只有一种分法了,a后面全为0,b后面和s相等,所以答案就出来了
找到第一个1的位置就行了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200010;
char a[N],b[N],s[N];
int t,n; 
 
int main(){
	cin>>t;
	while(t--){
		cin>>n>>s;
		int len = strlen(s);
		int l=len;
		for(int i=0;i<len;i++)
			if(s[i]=='1')
			{
				l=i;
				break;
			}
		for(int i=0;i<l;i++) cout<<(s[i]=='2'?1:0);
		if(l<len) 
		{
			cout<<1;
			for(int i=l+1;i<len;i++) cout<<0;
		}
		cout<<endl;
		for(int i=0;i<len;i++)
			if(i<l) cout<<(s[i]=='2'?1:0);
			else if(i==l) cout<<0; 
			else cout<<s[i];
		cout<<endl;
	}
	return 0;
}

D 已知n个动物都有一个种类,他们排成一个圈做游戏,让你为他们染色,只有一个条件相邻的两个不同种类的动物不能同色(这个还有一个隐含条件:相邻的两个同类型的动物可以同色也可以不同色)。
如果他们不是一个圈的话用两种颜色是一定可以染成功的,第一个染1然后依次向后遍历,如果当前与前一个类型相同染一样的颜色,否则染和前一个不同的颜色,这样一定是可行的,但是现在他们围成了一个圈,会多出来一个条件n和1是相邻的,那么我们按上面染色后n和1可能会发生冲突(前n个的颜色一定是可行的),他俩不同类型但是染了同种颜色这样是不合理的,那么我们可以怎样去修改呢,请看前面黑体部分,如果有相邻且同类型的时我们染成了同颜色,其实是可以染成不同颜色的,所以我们按照这样的思路再去染一遍,如果能使得n和1不同颜色那么两种颜色就是可行的,如果不能呢再加一种颜色一定是可行的,这里我没有仔细去证改变一次颜色后n的颜色没变就一定不会变了就直接染3了,凑合看吧,反正a了hhh。

#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int N = 400010;
int  a[N],b[N],s[N];
int t,n; 
int c[N];
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		bool flag=1;
		for(int i=1;i<=n;i++)
		 	cin>>a[i];
		int x=1,l=-1;//x颜色的种类,l记录类型相同且相邻的位置
		c[0]=1;//颜色
		a[0]=a[1];//确保第一个染成1
		for(int i=1;i<=n;i++) 
		{
			if(a[i]!=a[i-1]) 
			{	
				c[i]=3-c[i-1];//颜色反转
				x=2;
			}
			else c[i]=c[i-1],l=i;
		}
		if(a[n]!=a[1]&&c[n]==c[1])
		{
			if(l!=-1)//如果冲突从l向后再染一遍
			{
				c[l]=3-c[l-1];
				for(int i=l+1;i<=n;i++)
					if(a[i]!=a[i-1]) c[i]=3-c[i-1];
					else c[i]=c[i-1];
			}
			if(a[n]!=a[1]&&c[n]==c[1]) x=c[n]=3;
		}
		cout<<x<<endl;
		for(int i=1;i<=n;i++) cout<<c[i]<<' ';
		cout<<endl;	
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章