题解 | #自守数#
自守数
https://www.nowcoder.com/practice/88ddd31618f04514ae3a689e83f3ab8e
解法一:暴力破解
首先来介绍第一种解法,对 [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
作为基数,其到一个临界点的时候就会去发生一个变化那这个【临界点】是什么意思呢? [x] 当这个数是在10以内的话,那么它就是一个一位数,所以我们在对平方数取余的时候只需要取出最后面那一位就可以了,即%10[x] 当这个数是在100以内的话,那么它就是一个两位数,所以我们在对平方数取余的时候需要取出最后面的两位,即%100[x] 当这个数是在1000以内的话,那么它就是一个三位数,所以我们在对平方数取余的时候需要取出最后面的三位,即%1000 - 那经过上面这样一分析,你大概也能猜到这个基数
base
该如何变化了吧,也就是当这个i == 10
、i == 100
、i == 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; } }