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;
}