• 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;
    }
    
  • 相关阅读:
    Symmetric Order
    Red and Black
    Sticks(递归经典)
    Pascal Library
    cantor的数表
    OJ 调试技巧:VS2010 中 通过设置编译参数定义宏,无需修改源文件重定向标准输入输出
    strcmp
    最短周期串
    字母重排
    codeblocks 单步调试
  • 原文地址:https://www.cnblogs.com/neflibata/p/12871771.html
Copyright © 2020-2023  润新知