https://www.luogu.com.cn/problem/CF193E
属实是知识盲区了
通过打表不难发现在 膜
1
0
4
10^4
104下循环节是
1.5
×
1
0
4
1.5\times 10^4
1.5×104 膜
1
0
5
10^5
105下循环节是
1.5
×
1
0
5
1.5\times 10^5
1.5×105 膜
1
0
6
10^6
106下循环节是
1.5
×
1
0
6
1.5\times 10^6
1.5×106 膜
1
0
7
10^7
107下循环节是
1.5
×
1
0
7
1.5\times 10^7
1.5×107
以此类推类推,后面
m
o
d
??
1
0
i
\mod 10^i
mod10i循环节是
1.5
×
1
0
i
1.5 \times 10^i
1.5×10i
这相当于是保留了后
i
i
i位
容易得到 如果
f
i
b
(
x
)
m
o
d
??
1
0
i
=
n
m
o
d
??
1
0
i
fib(x) \mod 10^i = n \mod 10^i
fib(x)mod10i=nmod10i 一定是由
m
o
d
??
1
0
i
?
1
\mod 10^{i-1}
mod10i?1相等的那批加上
k
×
k\times
k×循环节长度得到的
于是可以先处理
1
0
5
10^5
105以内的,然后往后推即可
code:
#include<bits/stdc++.h>
#define N 2000050
#define ll long long
using namespace std;
ll mod;
ll mul(ll x, ll y) {
ll ret = 0;
for(; y; y >>= 1ll) {
if(y & 1) ret = (ret + x) % mod;
x = (x + x) % mod;
}
return ret;
}
struct MT {
ll a[2][2];
void init() {
for(int i = 0; i < 2; i ++)
for(int j = 0; j < 2; j ++) a[i][j] = (i == j);
}
MT operator * (const MT& o) const {
MT c;
for(int i = 0; i < 2; i ++)
for(int j = 0; j < 2; j ++) {
c.a[i][j] = 0;
for(int k = 0; k < 2; k ++)
c.a[i][j] = (c.a[i][j] + mul(a[i][k], o.a[k][j]) ) % mod;
}
return c;
}
};
MT qpow(MT x, ll y) {
MT ret; ret.init();
for(; y; y >>= 1, x = x * x) {
if(y & 1ll) ret = ret * x;
}
return ret;
}
ll fib(ll n) {
if(!n) return 0;
MT a;
a.a[0][0] = 0, a.a[0][1] = a.a[1][0] = a.a[1][1] = 1;
a = qpow(a, n - 1);
return a.a[1][1];
}
ll n, a[N], ls[N], f[N];
int gs, vis[N];
int main() {
scanf("%lld", &n);
if(!n) {
printf("0");
return 0;
}
if(n == 1) {
printf("1");
return 0;
}
mod = 100000;
f[0] = 0, f[1] = 1;
if(f[0] % mod == n % mod) a[++ gs] = 0;
if(f[1] % mod == n % mod) a[++ gs] = 1;
for(int i = 2; ; i ++) {
f[i] = (f[i - 1] + f[i - 2]) % mod;
if(f[i] == 1 && f[i - 1] == 0) break;
if(f[i] % mod == n % mod) a[++ gs] = i;
}
ll xhj = 150000;
for(mod = mod * 10; mod <= 10000000000000ll; mod = mod * 10, xhj = xhj * 10) {
int sz = 0;
for(int i = 1; i <= gs; i ++) {
for(int j = 0; j <= 9; j ++) {
if(fib(a[i] + j * xhj) == n % mod) {
ls[++ sz] = a[i] + j * xhj;
}
}
}
gs = sz;
for(int i = 1; i <= gs; i ++) a[i] = ls[i];
}
if(!gs) {
printf("-1");
return 0;
}
sort(a + 1, a + 1 + gs);
printf("%lld", a[1]);
return 0;
}
|