CF1598G
讲真,有点谔谔。
首先考虑若 \(a+b=x\) 那么 \(|a|,|b|,|x|\) 满足什么样的关系。不妨设 \(|a|\ge |b|\),不难发现 \(|x|\ge |a|\ge |x|-1\)。
那么分类讨论一下:
- \(|a|=|x-1|\),则 \(|b|=|x-1|\)。
- \(|a|=|x|\),设 \(\operatorname{lcp}(a, x)=p\),则 \(|b|=x-p\) 或 \(x-p-1\)。
总体上只有 \(\mathcal O(n)\) 种可能情况。随便枚举。\(\rm lcp\) 不会 Z 函数,用的二分 hash。
然后判断 \(a+b=x\),高精也就 \(\mathcal O(n^2/\omega)\) 吧,还是得 hash,注意多随机取几个模数,正确率高的一批。我用了 6 个。跑过了。
不太好追溯思路其实,我反正是纯靠直觉。大概总结一下的话,就是限制非常非常强,有效状态很少,就可以考虑通过构造类的方法筛一筛。
#include <bits/stdc++.h>
#define pb emplace_back
#define fir first
#define sec second
using i64 = long long;
const int maxn = 7e5 + 5;
char s[maxn], t[maxn];
int n, m;
i64 a[6][maxn], valx[6], hash[maxn], pw[maxn], Hash[maxn], p, base, pwt[6][maxn];
std::vector<i64> mods;
std::mt19937 rd((unsigned)time(0));
i64 dec(i64 x, i64 y) {
return (x - y) < 0 ? (x - y + p) : (x - y);
}
bool isprime(i64 x) {
if(x < 2)
return false;
for(i64 i = 2;i * i <= x;++ i)
if(!(x % i))
return false;
return true;
}
int lcp(int i) {
int l = 0, r = std::min(n - i + 1, m), mid;
while(l <= r) {
mid = (l + r) >> 1;
if(dec(hash[i + mid - 1], hash[i - 1] * pw[mid] % p) == Hash[mid])
l = mid + 1;
else
r = mid - 1;
}
return r;
}
std::vector<i64> gethash(int l, int r) {
std::vector<i64> A;
for(int k = 0;k < 6;++ k)
A.pb((a[k][r] - a[k][l - 1] * pwt[k][r - l + 1] % mods[k] + mods[k]) % mods[k]);
return A;
}
void check(int l, int r, int x, int y){
if(l > r||x > y||l < 1||r > n||x < 1||y > n)
return ;
std::vector<i64> A = gethash(l, r), B = gethash(x, y);
for(int k = 0;k < 6;++ k)
if((A[k] + B[k]) % mods[k] != valx[k])
return ;
printf("%d %d\n%d %d\n", l, r, x, y);
exit(0);
return ;
}
int main() {
scanf("%s %s", s + 1, t + 1);
n = strlen(s + 1);
m = strlen(t + 1);
pw[0] = 1;
while((int)mods.size() <= 5) {
i64 r = rd() % 998244353;
if(isprime(r))
mods.pb(r);
}
p = mods[rd() % 6];
do {
base = mods[rd() % 6];
} while(base == p);
for(int k = 0;k < 6;++ k) {
pwt[k][0] = 1;
for(int i = 1;i <= n||i <= m;++ i)
pwt[k][i] = 10ll * pwt[k][i - 1] % mods[k];
for(int i = 1;i <= n;++ i)
a[k][i] = (10ll * a[k][i - 1] % mods[k] + (s[i] ^ '0')) % mods[k];
for(int i = 1;i <= m;++ i)
valx[k] = (10ll * valx[k] % mods[k] + (t[i] ^ '0')) % mods[k];
}
for(int i = 1;i <= n;++ i)
hash[i] = (hash[i - 1] * base + s[i]) % p;
for(int i = 1;i <= m;++ i)
Hash[i] = (Hash[i - 1] * base + t[i]) % p;
for(int i = 1;i <= n;++ i)
pw[i] = pw[i - 1] * base % p;
for(int i = 1;i <= n;++ i) {
check(i, i + m - 2, i + m - 1, i + 2 * m - 3);
int z = lcp(i);
check(i, i + m - 1, i + m, i + m + (m - z) - 1);
check(i, i + m - 1, i + m, i + m + (m - z - 1) - 1);
check(i - (m - z), i - 1, i, i + m - 1);
check(i - (m - z - 1), i - 1, i, i + m - 1);
}
return 0;
}

浙公网安备 33010602011771号