|
| 1 | +--- |
| 2 | +title: 1922.统计好数字的数目:乘法原理+快速幂 |
| 3 | +date: 2025-04-14 00:31:36 |
| 4 | +tags: [题解, LeetCode, 中等, 数学, 乘法原理, 快速幂] |
| 5 | +categories: [题解, LeetCode] |
| 6 | +--- |
| 7 | + |
| 8 | +# 【LetMeFly】1922.统计好数字的数目:乘法原理+快速幂 |
| 9 | + |
| 10 | +力扣题目链接:[https://leetcode.cn/problems/count-good-numbers/](https://leetcode.cn/problems/count-good-numbers/) |
| 11 | + |
| 12 | +<p>我们称一个数字字符串是 <strong>好数字</strong> 当它满足(下标从 <strong>0</strong> 开始)<strong>偶数</strong> 下标处的数字为 <strong>偶数</strong> 且 <strong>奇数</strong> 下标处的数字为 <strong>质数</strong> (<code>2</code>,<code>3</code>,<code>5</code> 或 <code>7</code>)。</p> |
| 13 | + |
| 14 | +<ul> |
| 15 | + <li>比方说,<code>"2582"</code> 是好数字,因为偶数下标处的数字(<code>2</code> 和 <code>8</code>)是偶数且奇数下标处的数字(<code>5</code> 和 <code>2</code>)为质数。但 <code>"3245"</code> <strong>不是</strong> 好数字,因为 <code>3</code> 在偶数下标处但不是偶数。</li> |
| 16 | +</ul> |
| 17 | + |
| 18 | +<p>给你一个整数 <code>n</code> ,请你返回长度为 <code>n</code> 且为好数字的数字字符串 <strong>总数</strong> 。由于答案可能会很大,请你将它对<strong> </strong><code>10<sup>9</sup> + 7</code> <strong>取余后返回</strong> 。</p> |
| 19 | + |
| 20 | +<p>一个 <strong>数字字符串</strong> 是每一位都由 <code>0</code> 到 <code>9</code> 组成的字符串,且可能包含前导 0 。</p> |
| 21 | + |
| 22 | +<p> </p> |
| 23 | + |
| 24 | +<p><strong>示例 1:</strong></p> |
| 25 | + |
| 26 | +<pre> |
| 27 | +<b>输入:</b>n = 1 |
| 28 | +<b>输出:</b>5 |
| 29 | +<b>解释:</b>长度为 1 的好数字包括 "0","2","4","6","8" 。 |
| 30 | +</pre> |
| 31 | + |
| 32 | +<p><strong>示例 2:</strong></p> |
| 33 | + |
| 34 | +<pre> |
| 35 | +<b>输入:</b>n = 4 |
| 36 | +<b>输出:</b>400 |
| 37 | +</pre> |
| 38 | + |
| 39 | +<p><strong>示例 3:</strong></p> |
| 40 | + |
| 41 | +<pre> |
| 42 | +<b>输入:</b>n = 50 |
| 43 | +<b>输出:</b>564908303 |
| 44 | +</pre> |
| 45 | + |
| 46 | +<p> </p> |
| 47 | + |
| 48 | +<p><strong>提示:</strong></p> |
| 49 | + |
| 50 | +<ul> |
| 51 | + <li><code>1 <= n <= 10<sup>15</sup></code></li> |
| 52 | +</ul> |
| 53 | + |
| 54 | + |
| 55 | + |
| 56 | +## 解题方法:乘法原理+快速幂 |
| 57 | + |
| 58 | +每个偶数下标有5种选择,每个奇数下标有4种选择,每个元素之间的选择互补干扰冲突。 |
| 59 | + |
| 60 | +由于共有$a=\lfloor\frac{n+1}{2}\rfloor$个偶数位和$b=\lfloor\frac{n}{2}\rfloor$个奇数位,所以一共有$5^a4^b$种答案。 |
| 61 | + |
| 62 | +如何快速计算$m^n$?使用[快速幂](https://blog.letmefly.xyz/tags/%E5%BF%AB%E9%80%9F%E5%B9%82/)可在$\log n$的时间复杂度内求出。 |
| 63 | + |
| 64 | +快速幂原理方法请见:[这里](https://web.letmefly.xyz/Notes/ACM/Problems/%E5%BF%AB%E9%80%9F%E5%B9%82/)。 |
| 65 | + |
| 66 | ++ 时间复杂度$O(\log n)$ |
| 67 | ++ 空间复杂度$O(1)$ |
| 68 | + |
| 69 | +### AC代码 |
| 70 | + |
| 71 | +#### C++ |
| 72 | + |
| 73 | +```cpp |
| 74 | +/* |
| 75 | + * @Author: LetMeFly |
| 76 | + * @Date: 2025-04-13 17:00:20 |
| 77 | + * @LastEditors: LetMeFly.xyz |
| 78 | + * @LastEditTime: 2025-04-13 17:06:07 |
| 79 | + * @Description: AC,100.00%,51.97% |
| 80 | + */ |
| 81 | +typedef long long ll; |
| 82 | +const ll MOD = 1e9 + 7; |
| 83 | + |
| 84 | +class Solution { |
| 85 | +private: |
| 86 | + ll pow(ll a, ll b) { |
| 87 | + ll ans = 1; |
| 88 | + while (b) { |
| 89 | + if (b & 1) { |
| 90 | + ans = ans * a % MOD; |
| 91 | + } |
| 92 | + a = a * a % MOD; |
| 93 | + b >>= 1; |
| 94 | + } |
| 95 | + return ans; |
| 96 | + } |
| 97 | +public: |
| 98 | + int countGoodNumbers(long long n) { |
| 99 | + return pow(5, (n + 1) / 2) * pow(4, n / 2) % MOD; |
| 100 | + } |
| 101 | +}; |
| 102 | +``` |
| 103 | +
|
| 104 | +#### Python |
| 105 | +
|
| 106 | +Python用户可以无视手动实现快速幂。 |
| 107 | +
|
| 108 | +```python |
| 109 | +''' |
| 110 | +Author: LetMeFly |
| 111 | +Date: 2025-04-13 17:06:16 |
| 112 | +LastEditors: LetMeFly.xyz |
| 113 | +LastEditTime: 2025-04-13 17:06:17 |
| 114 | +''' |
| 115 | +MOD = 1000000007 |
| 116 | +
|
| 117 | +class Solution: |
| 118 | + def countGoodNumbers(self, n: int) -> int: |
| 119 | + return pow(5, (n + 1) // 2, MOD) * pow(4, n // 2, MOD) % MOD |
| 120 | +``` |
| 121 | + |
| 122 | +#### Java |
| 123 | + |
| 124 | +```java |
| 125 | +/* |
| 126 | + * @Author: LetMeFly |
| 127 | + * @Date: 2025-04-13 17:07:43 |
| 128 | + * @LastEditors: LetMeFly.xyz |
| 129 | + * @LastEditTime: 2025-04-14 00:07:21 |
| 130 | + * @Description: AC,100.00%,87.23% |
| 131 | + */ |
| 132 | +class Solution { |
| 133 | + private final long mod = 1000000007; |
| 134 | + |
| 135 | + private long pow(long a, long b) { |
| 136 | + long ans = 1; |
| 137 | + while (b > 0) { |
| 138 | + if ((b & 1) == 1) { |
| 139 | + ans = ans * a % mod; |
| 140 | + } |
| 141 | + a = a * a % mod; |
| 142 | + b >>= 1; |
| 143 | + } |
| 144 | + return ans; |
| 145 | + } |
| 146 | + |
| 147 | + public int countGoodNumbers(long n) { |
| 148 | + return (int)(pow(5, (n + 1) / 2) * pow(4, n / 2) % mod); |
| 149 | + } |
| 150 | +} |
| 151 | +``` |
| 152 | + |
| 153 | +#### Golang |
| 154 | + |
| 155 | +```go |
| 156 | +/* |
| 157 | + * @Author: LetMeFly |
| 158 | + * @Date: 2025-04-13 17:54:42 |
| 159 | + * @LastEditors: LetMeFly.xyz |
| 160 | + * @LastEditTime: 2025-04-14 00:05:17 |
| 161 | + * @Description: continue on subway,太晃了还是先算了 |
| 162 | + * @Description: AC,100.00%,63.16% |
| 163 | + */ |
| 164 | +package main |
| 165 | + |
| 166 | +var MOD1922 = int64(1000000007) |
| 167 | + |
| 168 | +func pow1922(a int64, b int64) int64 { |
| 169 | + ans := int64(1) |
| 170 | + for ; b > 0; b >>= 1 { |
| 171 | + if b & 1 == 1 { |
| 172 | + ans = ans * a % MOD1922 |
| 173 | + } |
| 174 | + a = a * a % MOD1922 |
| 175 | + } |
| 176 | + return ans |
| 177 | +} |
| 178 | + |
| 179 | +func countGoodNumbers(n int64) int { |
| 180 | + return int(pow1922(5, (n + 1) / 2) * pow1922(4, n / 2) % MOD1922) |
| 181 | +} |
| 182 | +``` |
| 183 | + |
| 184 | +> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/147200001)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2025/04/14/LeetCode%201922.%E7%BB%9F%E8%AE%A1%E5%A5%BD%E6%95%B0%E5%AD%97%E7%9A%84%E6%95%B0%E7%9B%AE/)哦~ |
| 185 | +> |
| 186 | +> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode) |
0 commit comments