To_Heart—题解——令人窒息的操作
描述
题目描述
果果想出两个令⼈窒息的操作,给你⼀个字符串 以及两个整数 和 。其中字符串 的⻓度为偶数, 且仅由数字0到9组成。
你可以在s上按任意顺序多次执⾏下⾯两个操作之⼀:
操作1:将a加到s中所有下标为奇数的元素上(下标从0开始)。数字⼀旦超过9就会变成0, 如此循环往复。例如,s=“3456"且a=5,则执⾏此操作后s变成"3951”。
操作2将s向右轮转b位。例如,s=“3456"且b=1,则执⾏此操作后s变成"6345” 。
请你帮果果求出在s上执⾏上述操作任意次后可以得到的字典序最⼩的字符串。
所谓字典序,⽐如两个字符串abcdef,bcd从第⼀个字符开始⽐较,第⼀个字符不相等a<b所以第⼀ 个字典序较⼩。若第⼀个相等,继续⽐较后续字符⽐如hi,history若其中⼀个没有后续的字符了,则 较短的串字典序较⼩。
输入格式
输出的第⼀⾏包括⼀个字符串s。 第⼆⾏包括两个正整数a,b。
输出格式
输出只有⼀⾏,表示你的答案。
样例
样例输入 1
5525
9 2
样例输出 1
2050
样例解释 1
初始:5525
操作2:2555
操作1:2454
操作1:2353
操作2:5323
操作1:5222
操作1:5121
操作2:2151
操作1:2050
题解
首先,对于操作1,因为我们要保证字典序最小,所以尽量把能改变的所有数中最靠前的数改变为零,设最靠前的数为n,我们依次枚举n,(n+a)%10,…,(n+9*a)%10,然后在里面找到最小的即可,再通过其改变来将所有的可以改变的数都改变。
然后,针对操作2,我们把它所有的移动情况全部枚举出来
根据裴蜀定理的推论(如上),可以确定移动过后的情况数最多有n-1种,再加上原来的数列,共有n种情况,开一个二维数组来存储所有情况,代码如下:
while(t!=0){
++tot; //tot为所有情况总数
for(int i=0;i<n;i++){
a[tot][i]=a[1][(i+t)%n];
}
t+=m;
t%=n;
}
但是,如果移动的次数为2的倍数,则原来的偶数位就永远是偶数位,永远无法进行操作1,所以进行分类讨论;
代码如下:
#include<bits/stdc++.h>
using namespace std;
int a[1005][1005];
bool f[1005];
int main(){
char s[1005];
cin>>s;
int n=strlen(s);
int m,x;
scanf("%d%d",&x,&m);
for(int i=0;i<n;i++){
a[1][i]=s[i]-'0';
}
m%=n;
if(m==0){
int sum=a[1][1];
int id=0;
int now=sum;
for(int i=1;i<=9;i++){
int nownow=sum+x*i;
if(nownow%10<now){
now=nownow%10;
id=i;
}
}
for(int i=0;i<n;i++){
if(i%2==1){
printf("%d",(a[1][i]+x*id)%10);
}
else
printf("%d",a[1][i]);
}
return 0;
}
int t=m;
int tot=1;
while(t!=0){
++tot;
for(int i=0;i<n;i++){
a[tot][i]=a[1][(i+t)%n];
}
t+=m;
t%=n;
}
if(m%2==0){
for(int i=1;i<=tot;i++){
int sum=a[i][1];
int id=0;
int now=sum;
for(int j=0;j<=9;j++){
int nownow=sum+x*j;
if(nownow%10<now){
now=nownow%10;
id=j;
}
}
for(int j=0;j<n;j++){
if(j%2==1){
a[i][j]=(a[i][j]+x*id)%10;
}
}
}
int nowmin=1;
for(int j=0;j<n;j++){
for(int i=1;i<=tot;i++){
if(f[i])
continue;
if(a[i][j]>a[nowmin][j]){
f[i]=1;
}
if(a[i][j]<a[nowmin][j]){
f[nowmin]=1;
nowmin=i;
}
}
}
for(int i=0;i<n;i++){
printf("%d",a[nowmin][i]);
}
return 0;
}
for(int i=1;i<=tot;i++){
int now_x=a[i][1];
int id_x=0;
int now_y=a[i][0];
int id_y=0;
for(int j=0;j<=9;j++){
int nownow=a[i][1]+x*j;
if(nownow%10<now_x){
now_x=nownow%10;
id_x=j;
}
nownow=a[i][0]+x*j;
if(nownow%10<now_y){
now_y=nownow%10;
id_y=j;
}
}
for(int j=0;j<n;j++){
if(j%2==1){
a[i][j]=(a[i][j]+x*id_x)%10;
}
else{
a[i][j]=(a[i][j]+x*id_y)%10;
}
}
}
int nowmin=1;
for(int j=0;j<n;j++){
for(int i=1;i<=tot;i++){
if(f[i])
continue;
if(a[i][j]>a[nowmin][j]){
f[i]=1;
}
if(a[i][j]<a[nowmin][j]){
f[nowmin]=1;
nowmin=i;
}
}
}
for(int i=0;i<n;i++){
printf("%d",a[nowmin][i]);
}
return 0;
}
/*
43987654
7 3
*/