3461. 判断操作后字符串中的数字是否相等 I
代码如下:
cpp
class Solution {
public:
bool hasSameDigits(string s) {
int n = s.size();
// 预处理 2 和 5 的幂次
int P2[n + 1], P5[n + 1];
P2[0] = P5[0] = 1;
for (int i = 1; i <= n; i++) P2[i] = P2[i - 1] * 2 % 10, P5[i] = P5[i - 1] * 5 % 10;
// 扩展欧几里得算法
auto exgcd = [&](this auto &&self, int a, int b, int &x, int &y) -> void {
if (b == 0) {
x = 1; y = 0;
return;
}
self(b, a % b, y, x);
y -= a / b * x;
};
// 求 s[l] 到 s[r] 合并起来的结果
auto calc = [&](int l, int r) {
int n = r - l;
// c:抛掉因数 2 和 5 后,组合数 mod 10 的结果
// two:组合数里因数 2 有几个
// five:组合数里因数 5 有几个
int c = 1, two = 0, five = 0, sm = 0;
for (int i = l, j = 0; ; i++, j++) {
// 按公式求和
sm = (sm + (s[i] - '0') * P2[two] * P5[five] * c) % 10;
if (i == r) break;
// 组合数递推式,先乘 (n - m)
int t = n - j;
while (t % 2 == 0) two++, t /= 2;
while (t % 5 == 0) five++, t /= 5;
c = c * t % 10;
// 组合数递推式,再除 (m + 1)
t = j + 1;
while (t % 2 == 0) two--, t /= 2;
while (t % 5 == 0) five--, t /= 5;
// 扩展欧几里得算法求逆元
int x, y;
exgcd(t, 10, x, y);
c = c * (x % 10 + 10) % 10;
}
return sm;
};
return calc(0, n - 2) == calc(1, n - 1);
}
};