codeforces-988E-Divisibility by 25【模拟?】
codeforces-988E-Divisibility by 25
自认为这是一道好题
题意:给出一个数n (1≤n≤10^18),每次可以交换相邻的两个数,问你最少交换几次可以被25整除,不允许有前导零
一个数想要被25整除,尾数就必须是25 50 75 00 其中的一种,具体为什么自己研究,如果不是,你来找我
那就好办了,比如说是要找25,那么为了保证交换次数最小,就应该从后往前找,找到5的位置是a,2的位置是b, 那么应该在前面的2就应该交换 l-2-b次,在后面的应该交换 l-1-a次,如果不明白怎么来的手动模拟一下
找位置的时候可以用string 的rfind函数,是可以从后往前找的!!
还有两个要注意的地方,在找到一个数之后要把它删掉,因为这个地方你可能交换之后他第一位就变成0了,如果交换后存在前导0,那么在答案中加上第一个不是0的位置就可以了
/*傻孩子之前直接从后往前遍历找'0','2''5''7'的位置然后计算,于是写了个巨长巨长的代码,也不是不可以,但是要考虑(比如465243,这样,你不仅要算l-2-b+l-1-a,还要再加1,因为你把2换到正确的位置之后5还要过去就把2挤到前面去了,然后43652比如这样就不用考虑之前的情况,还要考虑前导零等等等等一系列的情况,孩子改不起了,哭死,于是换了方法,牢骚释放完毕,总之想要写大模拟? 慎重*/
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int N=1e6+9; 5 const int inf=0x3f3f3f3f; 6 string s; 7 int solve(char x,char y) 8 { 9 string now=s; 10 int l=now.size();//要提前取字符串的长度,我删了之后再取,wa了几遍都没有发现 11 int a=now.rfind(y); 12 if(a!=-1) now.erase(a,1); 13 int b=now.rfind(x); 14 if(b!=-1) now.erase(b,1); 15 if(a==-1||b==-1) return inf; 16 int cnt=0; 17 for(int i=0;i<l;i++) 18 { 19 if(now[i]=='0') cnt++; 20 else break; 21 } 22 // printf("%d %d %d cnt a b\n",cnt,a,b); 23 return l-2-a+l-1-b+cnt; 24 } 25 int main() 26 { 27 cin>>s; 28 int l=s.size(); 29 int _50=solve('5','0'); 30 int _00=solve('0','0'); 31 int _25=solve('2','5'); 32 int _75=solve('7','5'); 33 // printf("%d %d %d %d\n",_00,_50,_25,_75); 34 int ans=min(min(min(_50,_00),_25),_75); 35 if(ans==inf) printf("-1\n"); 36 else printf("%d\n",ans); 37 return 0; 38 }