1. 程式人生 > >#121-【快速冪和慢速乘】序列的第K個數

#121-【快速冪和慢速乘】序列的第K個數

Description

BSNY 在學等差數列和等比數列,當已知前三項時,就可以知道是等差數列還是等比數列。現在給你序列的前三項,這個序列要麼是等差序列,要麼是等比序列,你能求出第 k 項的值嗎。 如果第 k 項的值太大,對 200907 取模。

Input

第一行一個整數 T,表示有 T 組測試資料;

對於每組測試資料,輸入前三項 a,b,c,然後輸入 k。

Output

對於每組資料輸出第 k 項的值,對 200907 取模。

Sample Input

2
1 2 3 5
1 2 4 5

Sample Output

5
16

HINT

 

樣例說明

第一組是等差序列,第二組是等比數列。

資料範圍與提示

對於全部資料,1≤T≤100,1≤a≤b≤c≤109,1≤k≤109

事實上,不開long long會玄學WA.

#include <iostream>

using namespace std;

long long slowmul(long long a, long long b) // 慢速乘有防止溢位的作用
{
	long long res = 0;
	
	while (b)
	{
		if (b & 1)
		{
			res += a;
			res %= 200907;
		}
		a <<= 1;
		b >>= 1;
	}
	
	return res;
}

long long quickpow(long long a, long long b) // 快速冪模板
{
	long long res = 1;
	
	while (b)
	{
		if (b & 1)
		{
			res *= a;
			res %= 200907;
		}
		a *= a;
		a %= 200907;
		b >>= 1;
	}
	
	return res;
}

int main(void)
{
	long long t, a, b, c, d;
	
	scanf("%lld", &t);
	while (t--)
	{
		scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
		if (a - b == b - c) // 如果是等差數列
		{
			printf("%lld\n", (a + slowmul(b - a, d - 1)) % 200907); // 慢速乘求第K個數
		}
		else // 如果不是等差數列,則是等比數列
		{
			printf("%lld\n", (a * quickpow(b / a, d - 1)) % 200907); // 快速冪求第K個數
		}
	}
	
	return 0;
}