Catalogue
1.Codeforces 898F Restoring the Expression
题目大意:给定一个字符串,将其划分成三个部分,使其满足一个加法等式。
设计思路:在这里首先我们考虑假定和为 n \;n\; n位数,那么两个加数的位数肯定都不会超过 n \;n\; n,并且其中一个加数一定是 n \;n\; n位或者 n − 1 \;n-1\; n−1位。这样我们先求出整个字符串的 H a s h \;Hash\; Hash函数,这里 b a s e \;base\; base取 10 \;10\; 10便于加法计算,然后枚举等号的位置,判断三个字符串的关系。
Solution:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
const ll base = 10;
const ll mod1 = 1e9 + 7, mod2 = 1e9 + 9;
int len;
char s[maxn];
ll res1, res2;
ll Hash1[maxn], Hash2[maxn], p1[maxn], p2[maxn];
inline ll getHash1(int l, int r)
{
return ((Hash1[r] - Hash1[l - 1] * p1[r - l + 1]) % mod1 + mod1) % mod1;
}
inline ll getHash2(int l, int r)
{
return ((Hash2[r] - Hash2[l - 1] * p2[r - l + 1]) % mod2 + mod2) % mod2;
}
inline void write(int pos1,int pos2)
{
for (int i = 1; i <= pos1; i++)
{
putchar(s[i]);
}
putchar('+');
for (int i = pos1 + 1; i <= pos2; i++)
{
putchar(s[i]);
}
putchar('=');
for (int i = pos2 + 1; i <= len; i++)
{
putchar(s[i]);
}
putchar(10);
}
inline bool check(int l, int r)
{
if (r - l > 1) //b不是1位数,要判断其是否含前导0,如果有则不符合要求
{
if (s[l + 1] == '0')
return false;
}
if (len - r > 1) //x不是1位数,要判断其是否含前导0,如果有则不符合要求
{
if (s[r + 1] == '0')
return false;
}
ll a1 = getHash1(1, l), a2 = getHash2(1, l);
ll b1 = getHash1(l + 1, r), b2 = getHash2(l + 1, r);
ll c1 = getHash1(r + 1, len), c2 = getHash2(r + 1, len);
if ((a1 + b1) % mod1 == c1 && (a2 + b2) % mod2 == c2)
{
write(l, r);
return true;
}
return false;
}
int main()
{
cin >> s + 1;
len = (int)strlen(s + 1);
if (s[1] == '0') //如果第一位是0,那么只能是0+b=c的情况
{
write(1, (len + 1) / 2);
return 0;
}
p1[0] = p2[0] = 1;
for (int i = 1; i <= len; i++)
{
Hash1[i] = (Hash1[i - 1] * base + s[i] - '0') % mod1;
Hash2[i] = (Hash2[i - 1] * base + s[i] - '0') % mod2;
p1[i] = p1[i - 1] * base % mod1;
p2[i] = p2[i - 1] * base % mod2;
}
for (int i = 1, j = len / 2; i <= j; i++)
{
if (len - 2 * i <= i)
{