kmjp's blog

競技プログラミング参加記です

yukicoder : No.534 フィボナッチフィボナッチ数

1000日目のブログ記事でした。
https://yukicoder.me/problems/no/534

問題

fib(n)をn番目のフィボナッチ数とする。
fib(fib(n)) mod (10^9+7)を求めよ。

解法

実験するとfib(n) mod (10^9+7)が周期*1 mod (10^9+7)を求めればよい。
フィボナッチ数列は自分も出題したことあるしいいよね…。
yukicoder : No.194 フィボナッチ数列の理解(1) - kmjp's blog

ll N;
ll mo=1000000007;

ll fib(ll k,ll a1=1,ll a2=1) {
	if(k==0) return 0;
	if(k==1) return a1;
	if(k==2) return a2;
	k-=2;
	ll R[2][2]={{1,0},{0,1}};
	ll A[2][2]={{1,1},{1,0}};
	
	while(k) {
		if(k%2) {
			ll S[2][2];
			S[0][0]=(A[0][0]*R[0][0]+A[0][1]*R[1][0])%mo;
			S[0][1]=(A[0][0]*R[0][1]+A[0][1]*R[1][1])%mo;
			S[1][0]=(A[1][0]*R[0][0]+A[1][1]*R[1][0])%mo;
			S[1][1]=(A[1][0]*R[0][1]+A[1][1]*R[1][1])%mo;
			swap(S,R);
		}
		ll T[2][2];
		T[0][0]=(A[0][0]*A[0][0]+A[0][1]*A[1][0])%mo;
		T[0][1]=(A[0][0]*A[0][1]+A[0][1]*A[1][1])%mo;
		T[1][0]=(A[1][0]*A[0][0]+A[1][1]*A[1][0])%mo;
		T[1][1]=(A[1][0]*A[0][1]+A[1][1]*A[1][1])%mo;
		swap(T,A);
		k>>=1;
	}
	return (R[0][0]+R[0][1])%mo;
	
	
}

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	
	cin>>N;
	if(N==0) return _P("0\n");
	mo=(1000000007+1)*2;
	ll M=fib(N,1,1);
	mo=1000000007;
	ll L=fib(M,1,1);
	cout<<L<<endl;
	
}

まとめ

(10^9+6)位の周期だろうと思ってがちゃがちゃ実験してたら、周期が(10^9+8)*2になってびっくり。

*1:10^9+7+1)*2)であることがわかる。 よってfib(fib(n) ((10^9+7+1)*2