Codeforces 988E(贪心+模拟)

传送门

题面:

E. Divisibility by 25
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given an integer nn from 11 to 10181018 without leading zeroes.

In one move you can swap any two adjacent digits in the given number in such a way that the resulting number will not contain leading zeroes. In other words, after each move the number you have cannot contain any leading zeroes.

What is the minimum number of moves you have to make to obtain a number that is divisible by 2525? Print -1 if it is impossible to obtain a number that is divisible by 2525.

Input

The first line contains an integer nn (1n10181≤n≤1018). It is guaranteed that the first (left) digit of the number nn is not a zero.

Output

If it is impossible to obtain a number that is divisible by 2525, print -1. Otherwise print the minimum number of moves required to obtain such number.

Note that you can swap only adjacent digits in the given number.

Examples
input
Copy
5071
output
Copy
4
input
Copy
705
output
Copy
1
input
Copy
1241367
output
Copy
-1
Note

In the first example one of the possible sequences of moves is 5071  5701  7501  7510  7150.


题面描述:

    给你一个1到1e18的数,每次你可以将相邻的两个数交换,问你是否能在若干次交换后,使新的数能被25整除。如果能则输出最小的交换次数,否则输出-1。

题目分析:

    我们需要发现,25的倍数有一个特性,无论其他数如何变,只要是以00、25、50、75结尾的数,必定是25的倍数。(因为对于这些数,无论前缀为多少,在除以5之后,最后的结尾总是能够为0或5,使得其结果还能被5整除)

    发现了这个规律之后,我们只需要贪心的进行比较,将原有的数贪心地分别以上述四个后缀为结尾,判断是否能够通过交换构成,如果能则贪心的选取最小的即可。

    而这个题还需要注意的一点前导0的处理,对于前导0的处理,因为每次的交换是相邻的交换的,因此第i位换到第j位只需要移动i-j次。所以如果出现构成00/25/50/75后缀后,出现前导0,我们只需要从第1位到第n-2位不断的寻找第一个非零的数,将此时的下标-1再加进cnt次数中进而跟答案比较即可。

代码:

    

#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
string str1,str2;
bool vis=0;
void Get(char a,char b,int n,int &ans){
    str2=str1;
    int cnt=0;
    int tmp=0;
    for(int i=n-1;i>=0;i--){//将最后一位置为字符a
        if(str2[i]==b){
            cnt++;
            for(int j=i;j<n-1;j++){
                swap(str2[j],str2[j+1]);
                tmp++;
            }
            break;
        }
    }
    for(int i=n-2;i>=0;i--){//将倒数第二位置为字符b
        if(str2[i]==a){
            cnt++;
            for(int j=i;j<n-2;j++){
                swap(str2[j],str2[j+1]);
                tmp++;
            }
            break;
        }
    }
    if(cnt==2){//如果能够构成后缀ab
        if(str2[0]!='0'){
            vis=1;
            //cout<<tmp<<endl;
            ans=min(ans,tmp);
        }//如果有前导0
        else{
            for(int i=0;i<n-2;i++){
                if(str2[i]!='0'){//从第1位到n-2位找到第一个不为0的数
                    tmp+=i;
                    vis=1;
                    ans=min(ans,tmp);
                    break;
                }
            }
        }
    }
}
int main()
{
    cin>>str1;
    int len=str1.length();
    int ans=INF;
    //四种情况贪心取最小
    Get('0','0',len,ans);
    Get('2','5',len,ans);
    Get('5','0',len,ans);
    Get('7','5',len,ans);
    if(vis) cout<<ans<<endl;
    else puts("-1");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_39453270/article/details/80548780