#10193. 「一本通 6.1 例 1」序列的第 k 个数 题解(快速幂模板)

【题目描述】https://loj.ac/problem/10193

BSNY 在学等差数列和等比数列,当已知前三项时,就可以知道是等差数列还是等比数列。现在给你序列的前三项,这个序列要么是等差序列,要么是等比序列,你能求出第 kkk 项的值吗。 如果第 kkk 项的值太大,对 200907200907200907 取模。

【输入格式】

第一行一个整数 TTT,表示有 TTT 组测试数据;

对于每组测试数据,输入前三项 a,b,ca, b, ca,b,c,然后输入 kkk。

【输出格式】

对于每组数据输出第 kkk 项的值,对 200907200907200907 取模。

【样例输入】

2
1 2 3 5
1 2 4 5

【样例输出】

5
16

思路:这道题就是快速幂的模板,运用到了&运算,&运算是属于位运算里面的,快速幂就是求一个数的n次方,当然也可以用快速傅里叶或者高精度来计算,但是这里主要是以快速幂为主。而快速幂的时间复杂度为O(log₂N),相对来讲不会超时。而快速幂的计算就是靠二进制来实现的,二进制是系统里面的,处理来讲会快很多。二进制就是0和1组成的,那么二进制是怎么转换的呢?

一、十进制转二进制(整数部分)
方法:用2辗转相除直到结果为1,将余数和最后的1从下向上的组合,就是我们想要的结果。
例如:60
60/2 = 30 余 0
30/2 = 15 余 0
15/2 = 7 余 1
7/2 = 3 余 1
3/2 = 1 余 1

所以十进制数60转为二进制数即为 11100

二、十进制小数转换为二进制小数
方法:乘2取整,顺序排列。
具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,或者达到所要求的精度为止。然后把取出的整数部分按顺序排列起来,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位。

例如:0.25
0.25*2 = 0.5 ------------整数部分:0
0.5*2 = 1.0 ------------整数部分:1

所以十进制数0.25转为二进制数即为 0.01

所以十进制数 60.25 转为二进制数即为 11100.01 

第二种暂时不用特别理解,掌握好第一种就好了。

那么接下来看代码

代码实现

/*
&运算,就是表示和&&有点类似,但是&&是两边的条件成立就成立
&也是这样,n&1表示如果两边的二进制的最后一位都为1,那么就成立,否则就不成立 
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define z 200907
typedef long long ll;
ll a,b,c,k,ans;
ll power(ll x,ll y)
{
	ll ret=1;
	while(y) //while(y!=0) 
	{
		if(y&1) ret=(ret*x)%z; //y&1是位运算,等同于y%2!=0 // (ret*x)%z就是区mod 
		y>>=1;//移动一位,二进制里面的,等同于 y/=2 
		x=x*x%z; //平方求mod 
		//可以这样是因为 次方求mod,可以边乘边mod,(mod就是求余数) 
	}
	return ret;
}
void solve()
{
	int d;
	scanf("%lld%lld%lld%lld",&a,&b,&c,&k);
	if(c-b==b-a) //表示等差数列 
	{
		d=(b-a)%z; //求公差 
		ans=(a+(k-1)%z*d)%z; //首项+要求的前一项*公差,
		//因为要求mod,所以要再里面求的时候mod一次,外面mod一次,就是边乘边mod 
	}
	else //等比数列 
	{
		d=(b/a)%z;//求公比 
		ans=a%z*power(d,k-1)%z;//通过不断用公差进行平方的mod运算,求出答案 
	}
	printf("%lld\n",ans);
}
int main()
{
	int t; scanf("%d",&t);
	while(t--) 
	{
		solve();//也可以直接将solve函数中的判断拉到这里
		/*
		scanf("%lld%lld%lld%lld",&a,&b,&c,&k);
		if(c-b==b-a)
		{ 
			ans=(a+(k-1)%z*(b-a)%z)%z; 
		}
		else
		{
			ans=a%z*power((b/a)%z,k-1)%z;
		}
		printf("%lld\n",ans)
		*/ 
	}
	return 0;
}

那么这道题就算是解决了,相对于线段树这些来说,难度系数大概为3。

然后这个 代码的power函数就是最精髓的地方,只要是快速幂,或者快速求mod就会有他的存在

猜你喜欢

转载自blog.csdn.net/qq_42367531/article/details/82024790