斐波那契取模10x的循环节是6∗10x(别问我怎么证。。。)
求第x项取模可以矩乘。
因此可以深搜枚举每一位然后验证减枝。
#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
char s[21];
int n;
ull ten[21],v,mod;
ull mul(ull x,ull y)
{
ull ret=0;
while(y)
{
if(y&1)ret=(ret+x)%mod;
x=(x+x)%mod;y>>=1;
}
return ret;
}
struct matrix
{
ull w[2][2];
friend matrix operator * (const matrix &r1,const matrix &r2)
{
matrix ret;
memset(&ret,0,sizeof(ret));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
(ret.w[i][j]+=mul(r1.w[i][k],r2.w[k][j]))%=mod;
return ret;
}
}mat;
matrix qpow(matrix x,ull y)
{
matrix ret;
ret.w[0][0]=1;ret.w[1][1]=1;
ret.w[0][1]=ret.w[1][0]=0;
while(y)
{
if(y&1)ret=ret*x;
x=x*x;y>>=1;
}
return ret;
}
ull fib(ull x)
{
mat.w[0][0]=0;mat.w[0][1]=1;
mat.w[1][0]=1;mat.w[1][1]=1;
mat=qpow(mat,x);
return mat.w[0][1];
}
void dfs(ull x,int y)
{
mod=ten[y];
if(fib(x)!=v%ten[y])return;
if(y==n){printf("%llu\n",x+6*ten[18]);exit(0);}
for(int i=0;i<10;i++)dfs(x+6*ten[y]*i,y+1);
}
int main()
{
//freopen("tt.in","r",stdin);
scanf("%s",s+1);n=strlen(s+1);
for(int i=1;i<=n;i++)v=v*10+s[i]-'0';
ten[0]=1;
for(int i=1;i<=20;i++)ten[i]=ten[i-1]*10;
for(int i=0;i<60;i++)
{
dfs(i,1);
}
puts("NIE");
return 0;
}