[力扣]2180统计各位数字之和为偶数的整数个数

题目

2180. 统计各位数字之和为偶数的整数个数

难度:简单

给你一个正整数 num ,请你统计并返回 小于或等于 num 且各位数字之和为 偶数 的正整数的数目。

正整数的 各位数字之和 是其所有位上的对应数字相加的结果。

示例 1:

输入: num = 4
输出: 2
解释:
只有 2 和 4 满足小于等于 4 且各位数字之和为偶数。

示例 2:

输入: num = 30
输出: 14
解释:
只有 14 个整数满足小于等于 30 且各位数字之和为偶数,分别是:
2、4、6、8、11、13、15、17、19、20、22、24、26 和 28 。

思路

没想到啊,官方解竟然是暴力解。。。。。。怪不得是简单题

1. 暴力枚举

暴力枚举,没啥好说的,从1到num枚举,检查每个是否满足各位加起来等于偶数。。。。

2. 数学方法

我们观察发现,在 [0...x][0...x] 的所有数中,每 10个数中,就有 55 个数的各位数字之和为偶数。例如,在 [0...9][0...9] 中,每 10个数中,就有 5个数的各位数字之和为偶数,分别是 0,2,4,6,80,2,4,6,8

因此,我们可以先算出numnum中有多少个 10 的倍数,然后乘以 5 再减去 1(排除 0 这个非正整数偶数),可以得到初始答案 ans=num10×51ans=\left\lfloor \frac{num}{10} \right\rfloor \times 5 - 1

接下来,我们还需要考虑剩下的 num%10+1num \% 10 + 1个数字中,有多少个数的各位数字之和为偶数。这些数字是否是偶数,跟数字的前面数字之和有关,因此,我们可以算出numnum的前面数字之和 s,那么剩余的数字中,还有num%10+2(s&1)2\left\lfloor \frac{num \% 10 + 2 - (s \& 1)}{2} \right\rfloor 个数的各位数字之和为偶数。累加到答案 ans 中即可。

我们不妨举个例子,假设numnum123123,那么前面 [0...119][0...119] 中一共有 12121010 的倍数,每个 1010 的倍数中有 55 个数的各位数字之和为偶数,因此,初始答案为ans=12×51=59ans=12 \times 5 - 1=59

剩下的数字分别是120,121,122,123120,121,122,123,每个数字的前两位数字之和为 s=1+2=3s = 1+2=3,是奇数,因此,剩下的数字中,只有 2 个数的各位数字之和为偶数,累加到答案 ans 中,最终答案为 ans+2=61ans+2=61

代码

1. 暴力

给下,意思下

func countEven(num int) (ans int) {
for i := 1; i <= num; i++ {
sum := 0
for x := i; x > 0; x /= 10 {
sum += x % 10
}
if sum%2 == 0 {
ans++
}
}
return
}

2. 数学

自己的思路

func countEven(num int) (ans int) {
ans = num/10*5 - 1
s := 0
for x := num / 10; x > 0; x /= 10 {
s += x % 10
}
ans += (num%10 + 2 - (s & 1)) >> 1
return
}