牛客HJ99 - 自守数【暴力 + 换位取模】

在这里插入图片描述

原题传送门


原题描述

牛客HJ99 - 自守数【暴力 + 换位取模】_第1张图片

  • 首先我们来看一下原题是怎么描述的,题面很简单,输入n,然后让我们去统计从1 ~ n之间的自守数有几个,那什么是【自守数】呢,上面也说到了,即一个数在平方之后该数的尾数等于该数自身的自然数

解法一:暴力破解

首先来介绍第一种解法,对 [0, n] 区间内的每个数字求平方,然后对n的几位数字进行是否相等判断,若相等则 count++

思路分析:

  • 这里就直接给出代码了,外层循环控制的是从1 ~ n,内部求出当前这个数的平方之后再去一一比对即可,此处的主要判断逻辑就在于这个tmp % 10 != pow_n % 10,通过对每一位去做一个比较,若是发现不相同的话那一定不是自守数
  • 最后在当前轮的循环结束后,若tmp == 0的话则表示所有的位数都比较过了均相同,不是中途break出来的,那么这个数就是【自守数】

代码详解:

int main() {
    int n = 0;
    int cnt = 0;

    cin >> n;

    for (int i = 0; i <= n;i++) {
        int tmp = i;
        int pow_n = pow(i, 2);

        while (tmp) {
            if(tmp % 10 != pow_n % 10)  
                break;      // 如果遇到不相同的话,直接break
            tmp /= 10;
            pow_n /= 10;
        }
        if (tmp == 0) {
            cnt++;
        }
    }
    cout << cnt << endl;
}

解法二: 换位取模

思路分析:

  • 然后我们再来说说第二种方法此方法我用到了一个base作为基数,其到一个临界点的时候就会去发生一个变化那这个【临界点】是什么意思呢?
    • 当这个数是在10以内的话,那么它就是一个一位数,所以我们在对平方数取余的时候只需要取出最后面那一位就可以了,即%10
    • 当这个数是在100以内的话,那么它就是一个两位数,所以我们在对平方数取余的时候需要取出最后面的两位,即%100
    • 当这个数是在1000以内的话,那么它就是一个三位数,所以我们在对平方数取余的时候需要取出最后面的三位,即%1000
  • 那经过上面这样一分析,你大概也能猜到这个基数base该如何变化了吧,也就是当这个i == 10i == 100i == 1000…这些临界的时候,就要去更换base

代码详解:

int main() {
    int n = 0;
    while (cin >> n) {
        long cnt = 0, base = 10;
        for (int i = 0; i <= n; ++i) {
            int pow_n = pow(i, 2);
            int tmp = i;
            // 如果i到达位数的临界点的话, 基数base要发生变化
            if (i == base) {
                base *= 10;
            }
            if (pow_n % base == i) {
                cnt++;
            }
        }
        cout << cnt << endl;
    }
}

在这里插入图片描述

你可能感兴趣的:(牛客算法笔记,算法)