Solution
设
a
长度为
可以尝试构造一个数
b
,使得
就等价于
x=a⋅10m+b≡2k(mod10n+m)
构造
k≥n+m
,那要满足这样的
k
就等价于
假如说现在有
x′a⋅10m
,要怎么构造满足上述两个条件的数
x
呢?
若
若
5∣x′
,则
x=x′+2n+m
。
如何解出
k
?
所以
2k−n−m≡x2n+m(mod5n+m)
。设
y=x2n+m
。
k=n+m+log2y
。
这里有一个结论
2
是
一个更广泛的结论:
g
是奇质数
证明:
- 设
d
是
φ(p) 的质因子,有 gpα−1(p−1)d=(gp−1d)pα−1≡gp−1d≢1(modpα) - 只需要证 gpα−2≢1(modpα) ,发现 xp≡1(modpa) , xp≡1(modpb)是b≤a 的充分条件。所以就等价于 g≢1(modp2) 。
但这个模数很大,BSGS是跑不过去的。
设
dy,i
为模
pi
意义下的
loggy
,有
di+1=di+jφ(pi),j∈[0,p)
,枚举就好了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int test, n;
ll a, b, t, l, x, y, MOD, tp, p5;
inline int diglen(ll x) {
static int cnt;
for (cnt = 0; x; cnt++) x /= 10;
return cnt;
}
inline ll Mul(ll a, ll b, ll MOD) {
ll c = 0;
while (b > 0) {
if (b & 1) c = (c + a) % MOD;
a = (a + a) % MOD; b >>= 1;
}
return c;
}
inline ll Pow(ll a, ll b, ll MOD) {
ll c = 1;
while (b > 0) {
if (b & 1) c = Mul(c, a, MOD);
a = Mul(a, a, MOD); b >>= 1;
}
return c;
}
int main(void) {
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
cin >> test;
while (test--) {
cin >> a; n = diglen(a);
tp = 1;
for (int m = 0; ; m++) {
x = a; MOD = 1ll << (n + m);
if (x % MOD != 0) x += MOD - x % MOD;
if (x % 5 == 0) x += MOD;
if (x % MOD == 0 && x % 5 != 0 && x - a < tp) {
y = x >> (n + m);
t = 0;
if (y % 5 == 0) t = -1;
if (y % 5 == 1) t = 0;
if (y % 5 == 2) t = 1;
if (y % 5 == 3) t = 3;
if (y % 5 == 4) t = 2;
p5 = 5;
for (int i = 1; i < n + m; i++){
while (Pow(2, t, p5 * 5) != y % (p5 * 5))
t += p5 / 5 * 4;
p5 *= 5;
}
cout << t + n + m << endl;
break;
}
a *= 10; tp *= 10;
}
}
}