藍橋杯試題 算法訓練 奇異的蟲羣

試題 算法訓練 奇異的蟲羣

資源限制
時間限制:1.0s 內存限制:256.0MB
問題描述
  在一個奇怪的星球上駐紮着兩個蟲羣A和B,它們用奇怪的方式繁殖着,在t+1時刻A蟲羣的數量等於t時刻A蟲羣和B蟲羣數量之和,t+1時刻B蟲羣的數量等於t時刻A蟲羣的數量。由於星際空間的時間維度很廣闊,所以t可能很大。OverMind 想知道在t時刻A蟲羣的數量對 p = 1,000,000,007.取餘數的結果。當t=1時 A種羣和B種羣的數量均爲1。
輸入格式
  測試數據包含一個整數t,代表繁殖的時間。
輸出格式
  輸出一行,包含一個整數,表示對p取餘數的結果
樣例輸入
10
樣例輸出
89
樣例輸入
65536
樣例輸出
462302286
數據規模和約定
  對於50%的數據 t<=10^9
  對於70%的數據 t<=10^15
  對於100%的數據 t<=10^18
提交代碼

import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		long n = in.nextLong();
		System.out.println(quickFib(n));
	}
	
	static long mod = 1000000007;
	static long quickAdd(long a, long b) {
		long ans = 0;
		while(b > 0) {
			if((b & 1) == 1) ans = (ans + a) % mod;
			a = (a << 1) % mod;
			b >>= 1;
		}
		return ans % mod;
	}
	
	static long[][] quickMulti(long[][] a, long[][] b) {
		long[][] ans = new long[2][2];
		long tmp = 0;
		for(int i = 0; i < 2; i ++) {
			for(int j = 0; j < 2; j ++) {
				tmp = 0;
				for(int k = 0; k < 2; k ++) {
					tmp = (tmp + quickAdd(a[i][k], b[k][j])) % mod;
				}
				ans[i][j] = tmp;
			}
		}
		return ans;
	}
	
	static long[][] quickPow(long[][] a, long b) {
		long[][] ans = new long[2][2];
		ans[0][0] = ans[1][1] = 1;
		ans[0][1] = ans[1][0] = 0;
		while(b > 0) {
			if((b & 1) == 1) ans = quickMulti(ans, a);
			a = quickMulti(a, a);
			b >>= 1;
		}
		return ans;
	}
	
	static long quickFib(long a) {
		long[][] ans = new long[2][2];
		long[][] tmp = new long[2][2];
		tmp[0][0] = tmp[0][1] = tmp[1][0] = 1;
		tmp[1][1] = 0;
		ans = quickPow(tmp, a);
		return ans[0][0] % mod;
	}
	
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章