【题解】CF678D Iterated Linear Function

博客详细介绍了如何使用待定系数法求解数列的通项公式,结合快速幂算法处理大整数模运算。当数列满足特定递推关系时,通过转换将数列转换为等比数列,进而求出通项公式。同时,针对A=1的特殊情况,博客给出了等差数列的解决方案。最后,提供了完整的C++代码实现,适用于处理大规模数据并避免除法运算。
摘要由CSDN通过智能技术生成

Step 0:食用前准备


  • 知识:带数列的通项公式
  • 只需要具备初一基本代数知识。
  • 代码很短,数学题,准备好足够的耐心看完推导过程。

Step 1:题意简化


有一个数列 g g g ,满足:

  • g 0 = x g_0=x g0=x x x x 为给定数;
  • g i + 1 = A × g i + B g_{i+1}=A\times g_i+B gi+1=A×gi+B A A A B B B 为给定数。

g n g_n gn 的值,并对 1 0 9 + 7 10^9+7 109+7 取模。

Step 2:分析


g 0 = x g_0=x g0=x g 1 = A × g 0 + B g_1=A\times g_0+B g1=A×g0+B g 2 = A × g 1 + B g_2=A\times g_1+B g2=A×g1+B ,… ,感觉像套娃的样子。

发现每次都会先乘上一个 A A A ,那么最后的结果猜测是与 A n A^n An 有关的东西。

那也不能让它一直套下去,得想办法求出 g g g 的通项公式才行。

今天介绍一种求数列通项公式的方法:待定系数法求数列通项公式

强烈推荐百度搜索“待定系数法求数列的通项公式”。

Step 3:计算


Part 1

g n + 1 + k = A ( g n + k ) g_{n+1}+k=A(g_n+k) gn+1+k=A(gn+k) n ∈ N n\in N nN . // n ∈ N n\in N nN 指的是 n n n 属于自然数。

把上述式子拆开、移项、合并同类项 g n + 1 = A × g n + ( A − 1 ) k g_{n+1}=A\times g_n+(A-1)k gn+1=A×gn+(A1)k .

又依题有: g i + 1 = A × g i + B g_{i+1}=A\times g_i+B gi+1=A×gi+B ,两式对比 B = ( A − 1 ) k B=(A-1)k B=(A1)k

除过去求出 k k k 得: k = B A − 1 k=\frac{B}{A-1} k=A1B . //为了让思路更加清晰,这里先不考虑 A − 1 = 0 A-1=0 A1=0 的情况,后面会补充说明。

在一开始我们设了一个式子: g n + 1 + k = A ( g n + k ) g_{n+1}+k=A(g_n+k) gn+1+k=A(gn+k)

那么把算出来的 k k k 代进去得 g n + 1 + B A − 1 = A ( g n + B A − 1 ) g_{n+1}+\frac{B}{A-1}=A(g_n+\frac{B}{A-1}) gn+1+A1B=A(gn+A1B)

哇!是不是有点像等比数列?


Part 2

我们 h n = g n + B A − 1 h_n=g_n+\frac{B}{A-1} hn=gn+A1B ,再对比上面最新的式子, h h h 恰好就是公比为 A A A 的等比数列!

h n + 1 = A × h n h_{n+1}=A\times h_n hn+1=A×hn

由于 h 0 = g 0 + B A − 1 h_0=g_0+\frac{B}{A-1} h0=g0+A1B那么 h n = A n × h 0 = A n × ( g 0 + B A − 1 ) h_n=A^n\times h_0=A^n\times (g_0+\frac{B}{A-1}) hn=An×h0=An×(g0+A1B)

所以 h h h 的通项公式就有了,但是我们的终极目标是求 g g g 的通项公式,那怎么办?

怎么办呢?Part 2的最开始设了 h n = g n + B A − 1 h_n=g_n+\frac{B}{A-1} hn=gn+A1B ,可以得出:

g n = h n − B A − 1 = A n × ( g 0 + B A − 1 ) − B A − 1 g_n=h_n-\frac{B}{A-1}=A^n\times (g_0+\frac{B}{A-1})-\frac{B}{A-1} gn=hnA1B=An×(g0+A1B)A1B

再整理一下上面的式子,题目将 g 0 g_0 g0 输入为 x x x ,顺便替换掉: g n = A n × g 0 + ( A n − 1 ) × B A − 1 = A n × x + ( A n − 1 ) × B A − 1 g_n=A^n\times g_0+(A^n-1)\times \frac{B}{A-1}=A^n\times x+(A^n-1)\times \frac{B}{A-1} gn=An×g0+(An1)×A1B=An×x+(An1)×A1B

好了, g n g_n gn 的通项公式就解决了,我们用了 A A A B B B x x x ,来表示出了 g n g_n gn


Part 3

现在还有一个小问题:刚才把 g n g_n gn 求出来了,那这个式子里 A − 1 A-1 A1 分母等于 0 0 0 怎么办?也就是 A = 1 A=1 A=1 怎么办?

那太好办了,如果 A = 1 A=1 A=1 ,也就是说 g i + 1 = g i + B g_{i+1}=g_i+B gi+1=gi+B g g g 为等差数列。

这个时候 g n = g 0 + n × B g_n=g_0+n\times B gn=g0+n×B

输入的时候特判一下就可以了。

if(a==1){
	cout<<(x+n%mod*b%mod)%mod<<endl;
	return 0;
}

Step 4:实现上的一些细节


式子求出来了,结果发现输入有亿点点大,而且这个式子是分式,也就是还要算除法。

输入较大,用上快速幂,记得及时取模。

在计算的过程中需要除以 A − 1 A-1 A1 ,这个时候除以 A − 1 A-1 A1 就相当于乘 A − 1 A-1 A1 m o d mod mod 意义下的逆元。

由于题目里要求取模的 1 0 9 + 7 10^9+7 109+7 是质数,所以这份代码是根据费马小定理求的逆元,不明白的可以自行学习一下~~(具体方法:百度搜索“费马小定理求逆元”)~~。

long long inv=pw(a-1,mod-2); //pw是快速幂的函数

Step 5:完整代码


#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;

unsigned long long a,b,n,x;//开一下long long

long long pw(long long a,long long b)
{
	long long ans=1,base=a;
	while(b!=0){
		if(b&1!=0) ans=ans*base%mod;
		base=base*base%mod;
		b>>=1;
	}
	return ans%mod;
}

signed main()
{
	cin>>a>>b>>n>>x;
	if(a==1){
		cout<<(x+n%mod*b%mod)%mod<<endl;
		return 0;
	}
	long long inv=pw(a-1,mod-2);//求a-1的逆元
	long long power=pw(a,n);//求a的n次方
	long long ans=((power-1)*inv%mod*b%mod+x%mod*power%mod)%mod;//根据刚才的式子代入即可
	cout<<ans<<endl;
	return 0;
}

ps:数学不好,有问题尽管指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值