AtCoder题解—— AtCoder Beginner Contest 181 —— D - Hachi

题目相关

题目链接

AtCoder Beginner Contest 181 D 题,https://atcoder.jp/contests/abc181/tasks/abc181_d。

Problem Statement

Given is a digit sequence S consisting of the digits from 1 through 9.

Takahashi, the bee, loves multiples of 8. He is trying to make a multiple of 8 by permuting the digit sequence S.

Determine whether it is possible.

Input

Input is given from Standard Input in the following format:

S

Output

If it is possible to make a multiple of 8 by permuting the digit sequence S, print Yes; otherwise, print No.

Samples1

Sample Input 1

1234

Sample Output 1

Yes

Explaination

For example, permuting 1234 into 1432 results in a multiple of 8.

Samples2

Sample Input 2

1333

Sample Output 2

No

Explaination

There is no way to permute 1333 into a multiple of 8.

Samples3

Sample Input 3

8

Sample Output 3

Yes

Constraints

  • 1≤|S|≤2×10^5
  • Each character of S is one of the digits from 1 through 9.

题解报告

题目翻译

给一个有数字 1 到 9 构成的字符串,判断能否通过交换位置,使得这个字符串对应的数字可以被 8 整除。

题目分析

看到这个题目,第一反应是全排序,也就是根据提供的字符串列出全排列,然后再验证是否能被 8 整除。例如字符串为 1234,我们可以通过 STL 的 next_permutation() 函数实现。这样我们写道 1432 的时候,这个数字可以被 8 整除。

但是看到数据长度 2×10^5 的时候,就知道这个方法是不可行的。

仔细思考后,又是一个数学题。这题的核心数学是如何判断一个数字能被 8 整除。

判断数字能否被 8 整除

通过数学归纳法,我们可以发现。由于本题没有数字 0。

  1. 数据长度为 1 的时候,8 可以被 8 整除。
  2. 数据长度为 2 的时候,16、24、32、40、48、56、64、72、80、88、96,这些数字可以被 8 整除。
  3. 数据长度大于 2 的时候,末尾 3 位为 104、112、...、984、992,这些数字能被 8 整除。

这样我们就找到了规律。

结论

本题就是统计是否有这样的规律,而不需要去构造字符串。如何使用这样规律呢?

数据长度为 1 和 2,只需要特判就可以了。

数据长度超过 2 的,将对应的字符串每位数字的个数统计出来。使用如下的伪码:

for (int i=104; i<1000; i++) {
    统计数字 i 变为有几个 1 ~ 9 构成。将结果保存在数组 tmp[10] 中
    比对 tmp 和 num 数组
    只要 tmp 数组中的任意一个数据大于 num 数组,说明不能构成
    tmp 数组中所有数据都小于等于 num 数组,说明可以构成
}

例如我们输入 98433333333333333333333333333333333333333666666。我们统计每个数字出现的个数,即统计数字 1 ~ 9 出现的个数。这样我们可以得到下面的数组:

num[0]=0;
num[1]=0;
num[2]=0;
num[3]=38;
num[4]=1;
num[5]=0;
num[6]=6;
num[7]=0;
num[8]=1;
num[9]=1;

然后判断这些数字能否组合成为 104、112、...、984、992 这样的数字。当我们遍历到 336 的时候,也就是说末尾三个数字变成 336,就可以被 8 整除。

例如我们输入 1333。我们统计每个数字出现的个数,即统计数字 1 ~ 9 出现的个数。这样我们可以得到下面的数组:

num[0]=0;
num[1]=1;
num[2]=0;
num[3]=3;
num[4]=0;
num[5]=0;
num[6]=0;
num[7]=0;
num[8]=0;
num[9]=0;

然后判断这些数字能否组合成为 104、112、...、984、992 这样的数字。整个遍历完成后,发现没有办法构成被 8 整除的数据。

例如 104 对应的统计数据如下:

num[0]=1;
num[1]=1;
num[2]=0;
num[3]=0;
num[4]=1;
num[5]=0;
num[6]=0;
num[7]=0;
num[8]=0;
num[9]=0;

其中 tmp[0]>num[0],说明没法构成 104。其他数据以此类推。

AC 参考代码

//https://atcoder.jp/contests/abc181/tasks/abc181_d
//D - Hachi
#include 

using namespace std;

string str;//保存字符串
int num[10];//数字0~9

bool judge(int x) {
    int t=x;
    int tmp[10]={};
    while (t) {
        tmp[t%10]++;
        t/=10;
    }
    for (int i=0; i<10; i++) {
        if (tmp[i]>num[i]) {
            return false;
        }
    }
    return true;
}

int main() {
    cin>>str;

    int len=str.length();
    for (int i=0; i

时间复杂度

应该是 O(N),有点不是很确定。惭愧。

你可能感兴趣的:(OJ题解,#,AtCoder题解,AtCoder,AtCoder题解,ABC181,D题,Hachi)