5104: Fib数列

首先发现递推是解决不了这个问题的.

考虑用通项公式解决.

有公式 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=5 1((21+5 )n(215 )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) a5 1((21+5 )n(215 )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 )(15 )(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+5 2)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) Txn(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) Txn(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(xn2T)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;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值