首先发现递推是解决不了这个问题的.
考虑用通项公式解决.
有公式 f n = 1 5 ( ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ) f_n=\frac{1}{\sqrt 5}((\frac{1+\sqrt 5}{2})^n-(\frac{1-\sqrt 5}{2})^n) fn=51((21+5)n−(21−5)n)
那么即求解:
a ≡ 1 5 ( ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ) ( m o d    p ) a \equiv \frac{1}{\sqrt 5}((\frac{1+\sqrt 5}{2})^n-(\frac{1-\sqrt 5}{2})^n) (\mod p) a≡51((21+5)n−(21−5)n)(modp)
a 5 ≡ ( 1 + 5 2 ) n − ( ( 1 − 5 ) ( 1 + 5 ) 2 ( 1 + 5 ) ) n ( m o d    p ) a \sqrt 5 \equiv (\frac{1+\sqrt 5}{2})^n-(\frac{(1-\sqrt 5)(1+\sqrt 5)}{2(1+\sqrt 5)})^n (\mod p) a5≡(21+5)n−(2(1+5)(1−5)(1+5))n(modp)
a 5 ≡ ( 1 + 5 2 ) n − ( − 2 1 + 5 ) n ( m o d    p ) a \sqrt 5 \equiv (\frac{1+\sqrt 5}{2})^n-(- \frac{2}{1+\sqrt 5})^n (\mod p) a5≡(21+5)n−(−1+52)n(modp)
首先知道5在mod p的意义下有二次剩余,那么解出 5 \sqrt 5 5
令 x = 1 + 5 2 \frac{1+\sqrt 5}{2} 21+5 ,T = a 5 \sqrt 5 5
原式化为:
T ≡ x n − ( − 1 x ) n ( m o d    p ) T \equiv x^n - (-\frac{1}{x})^n(\mod p) T≡xn−(−x1)n(modp)
T ≡ ( x n ) 2 − ( − 1 ) n x n ( m o d    p ) T \equiv \frac{(x^n)^2 - (-1)^n}{x^n}(\mod p) T≡xn(xn)2−(−1)n(modp)
T 2 4 + ( − 1 ) n ≡ ( x n − T 2 ) 2 ( m o d    p ) \frac{T^2}{4} + (-1)^n \equiv (x^n - \frac{T}{2})^2(\mod p) 4T2+(−1)n≡(xn−2T)2(modp)
再次运用二次剩余求解 T 2 4 + ( − 1 ) n \frac {T^2}{4} + (-1)^n 4T2+(−1)n即可,此时要分奇偶讨论,
解出该值即可用bsgs求出最终答案.
注意 x n x^n xn - T 2 \frac{T}{2} 2T可正可负,也要分类一下
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x;i <= y; ++ i)
#define repd(i,x,y) for(register int i = x;i >= y; -- i)
using namespace std;
typedef long long ll;
template<typename T>inline bool chkmin(T&x,T y) { return x > y ? x = y,1 : 0; }
template<typename T>inline void read(T&x)
{
char c;int sign = 1;x = 0;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int mod = 1e9 + 9;
struct DATA
{
int x,y,w;
DATA(){}
DATA(int _x,int _y,int _w) { x = _x,y = _y,w = _w; }
inline DATA operator * (DATA a)
{
return DATA((1ll * x * a.x % mod + 1ll * y * a.y %mod * w % mod)% mod,
(1ll * x * a.y + 1ll * y * a.x) % mod,w);
}
inline DATA ksm(int y)
{
DATA ans = DATA(1,0,w);
DATA x = *this;
while(y)
{
if(y&1) ans = ans * x;
x = x * x; y >>= 1;
}
return ans;
}
};
inline int ksm(int x,int y)
{
int ans = 1;
while(y)
{
if(y&1) ans = 1ll * ans * x % mod;
x = 1ll * x * x % mod; y >>= 1;
}
return ans;
}
inline int get(int n)
{
if(ksm(n,(mod-1)/2) == mod - 1) return -1;
int w,x;
while(1)
{
x = rand() % mod;
w = (1ll * x * x - n )% mod;
w = (w + mod) % mod;
if(ksm(w,(mod-1)/2) == mod - 1) break;
}
DATA a = DATA(x,1,w);
a = a.ksm((mod + 1)/2);
return a.x;
}
map<int,int>mp[2];
inline int bsgs(int n,bool k,int z,int x)
{
int t = ksm(ksm(x,z),mod-2);
rep(i,0,z)
{
if(mp[(i*z)&1^k][n]) return mp[(i*z)&1^k][n] - 1 + i * z;
n = 1ll * n * t % mod;
}
return INT_MAX;
}
int main()
{
int k = get(5);int x = 1ll * (1 + k) * ksm(2,mod-2) % mod;
int a; read(a); a = 1ll * a * k % mod;
int z = ceil(sqrt(mod)),t = 1;
rep(i,0,z)
{
if(!mp[i&1][t]) mp[i&1][t] = i + 1;
t = (1ll * t * x) % mod;
}
int ans = INT_MAX,q,e = 1ll * a * ksm(2,mod-2)%mod;
if((q = get((1 + 1ll * a * a % mod * ksm(4,mod-2))% mod)) != -1)
{
chkmin(ans,bsgs((q+e)%mod,0,z,x));
chkmin(ans,bsgs((mod-q+e)%mod,0,z,x));
}
if((q = get((mod - 1 + 1ll*a*a%mod * ksm(4,mod-2))% mod)) != -1)
{
chkmin(ans,bsgs((q+e)%mod,1,z,x));
chkmin(ans,bsgs((mod-q+e)%mod,1,z,x));
}
if(ans == INT_MAX) puts("-1");
else printf("%d\n",ans);
return 0;
}