题解:CF1698G Long Binary String
Petit_Souris
·
·
题解
very cool problem
将问题表示成 \bmod 2 意义下形式幂级数的形式。
首先把前导零删掉,最后答案平移一下。设 F(x) 为输入串对应的多项式,那么我们要求的就是选择一些 F(x)x^t 加起来,得到形如 1 + x ^ k 的结果,那么答案就是 (0, k)。
显然最后式子可以表示成 F(x)G(x) 的形式,G(x) 为任意多项式。即求 F(x)G(x) = 1 + x ^ k。
两边对 F(x) 取模,得到 x ^ k \equiv 1 \pmod {F(x)}(这是因为在 \bmod 2 意义下)。
看起来很像一个 BSGS 问题,而由于 \deg F(x) < n,因此根据抽屉原理,k\le 2^{n - 1}。(\bmod F(x) 后只有 0\sim n - 2 次项,每个系数两种方法,因此 2^{n - 1} + 1 个 k 中至少有两个相同的)
因此我们设 k = uB - v,其中 B = \mathcal O(2^{n / 2})。那么即求 x ^ {uB} \equiv x ^ v \pmod {F(x)}。预处理出 [0, B] 内的 x ^ v 和 x ^ {uB},枚举 u 找到对应的 v 即可。
代码我觉得我写的很帅。
```cpp
#include <bits/stdc++.h>
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using namespace std;
template <class T>
using Ve = vector<T>;
#define ALL(v) (v).begin(), (v).end()
#define pii pair<ll, ll>
#define rep(i, a, b) for(ll i = (a); i <= (b); ++i)
#define per(i, a, b) for(ll i = (a); i >= (b); --i)
#define pb push_back
bool Mbe;
ll read() {
ll x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
void write(ll x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
const ll B = 4e5 + 9;
ll n;
ull f, pw1[B + 5], pw2[B + 5];
char s[40];
ull Mul(ull F, ull G) {
__uint128_t H = 0;
rep(i, 0, n - 1) {
if((F >> i) & 1) H ^= ((__uint128_t)G << i);
}
per(i, 2 * (n - 1), n - 1) {
if((H >> i) & 1) H ^= ((__uint128_t)f << (i - n + 1));
}
return H;
}
map<ull, ll> mp;
bool Med;
int main() {
cerr << fabs(&Med - &Mbe) / 1048576.0 << "MB\n";
scanf("%s", s), n = strlen(s);
reverse(s, s + n);
ll pre = 0;
while(n && s[n - 1] == '0') --n, ++pre;
if(!n) return puts("-1"), 0;
reverse(s, s + n);
while(s[n - 1] == '0') --n;
rep(i, 0, n - 1) {
if(s[i] == '1') f |= (1ull << i);
}
pw1[0] = 1;
rep(i, 1, B) pw1[i] = Mul(pw1[i - 1], 2);
rep(i, 0, B - 1) mp[pw1[i]] = i;
pw2[0] = 1;
rep(i, 1, B) pw2[i] = Mul(pw2[i - 1], pw1[B]);
rep(u, 1, B) {
if(mp.count(pw2[u])) {
ll v = mp[pw2[u]];
write(pre + 1), putchar(' '), write(pre + 1 + u * B - v), putchar('\n');
return 0;
}
}
cerr << "\n" << clock() * 1.0 / CLOCKS_PER_SEC * 1000 << "ms\n";
return 0;
}
```