generator 1【矩阵快速幂】

题目描述
You are given four positive integers x 0 , x 1 , a , b x_0, x_1, a, b x0,x1,a,b. And you know x i = a ⋅ x i − 1 + b ⋅ x i − 2 x_i = a \cdot x_{i-1} + b \cdot x_{i-2} xi=axi1+bxi2 for all i ≥ 2 i \ge 2 i2.

Given two positive integers n, and MOD, please calculate x n x_n xn modulo MOD.

Does the problem look simple? Surprise! The value of n may have many many digits!

输入描述:
The input contains two lines.
The first line contains four integers x 0 , x 1 , a , b x_0, x_1, a, b x0,x1,a,b ( 1 ≤ x 0 , x 1 , a , b ≤ 1 0 9 ) (1 \le x_0, x_1, a, b \le 10^9) (1x0,x1,a,b109)
The second line contains two integers n n n, MOD ( 1 ≤ n &lt; 1 0 ( 1 0 6 ) , 1 0 9 &lt; M O D ≤ 2 × 1 0 9 , n   h a s   n o   l e a d i n g   z e r o ) (1 \le n &lt; 10^{(10^6)}, 10^9 &lt; MOD \le 2 \times 10^9 , n\ has\ no\ leading\ zero) (1n<10(106),109<MOD2×109,n has no leading zero).

输出描述:
Print one integer representing the answer.

示例1
输入
1 1 1 1
10 1000000001
输出
89
说明
The resulting sequence x is Fibonacci sequence. The 11-th item is 89.

示例2
输入
1315 521 20185 5452831
9999999999999999999999999999999999999 1000000007
输出
914730061

题目大意:
已知公式 x i = a ⋅ x i − 1 + b ⋅ x i − 2 x_i=a \cdot x_{i-1} + b \cdot x_{i-2} xi=axi1+bxi2
第一行输入 x 0 , x 1 , a , b x_0,x_1,a,b x0,x1,a,b
第二行输入 n , p n,p n,p
x n % p x_n\%p xn%p的值

解题思路:
由于此题 n n n的数据范围很大,而且又知道公式,所以可以很容易想到是矩阵快速幂的裸题,但由于 n n n的范围很大,所以需将二进制的快速幂写法改为十进制。
由于 x i = a ⋅ x i − 1 + b ⋅ x i − 2 x_i=a \cdot x_{i-1} + b \cdot x_{i-2} xi=axi1+bxi2
所以
∣ x n + 1 x n 0 0 ∣ = ∣ x 0 x 1 0 0 ∣ ∗ ∣ a 1 b 0 ∣ n \begin{vmatrix} x_{n+1} &amp; x_n \\ 0 &amp; 0 \end{vmatrix}=\begin{vmatrix} x_0 &amp; x_1 \\ 0 &amp; 0 \end{vmatrix}*\begin{vmatrix} a &amp; 1 \\ b &amp; 0 \end{vmatrix}^n xn+10xn0=x00x10ab10n
因此直接敲矩阵快速幂即可。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <set>
#include <utility>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define inf 0x3f3f3f3f
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define lep(i,l,r) for(int i=l;i>=r;i--)
#define ms(arr) memset(arr,0,sizeof(arr))
//priority_queue<int,vector<int> ,greater<int> >q;
const int maxn = (int)1e5 + 5;
const ll mod = 1e9+7;
struct node
{
	ll arr[2][2];
	node() {
		ms(arr);
	}
};
ll p;
node mul(node a,node b) {
	node c;
	for(int i=0;i<2;i++) {
		for(int j=0;j<2;j++) {
			for(int k=0;k<2;k++) {
				c.arr[i][j]=(c.arr[i][j]+(a.arr[i][k]*b.arr[k][j])%p)%p;
			}
		}
	}
	return c;
}
char str[1001000];
node b1,base;
int len;
ll quickpow() {
	for(int i=len-1;i>=0;i--) {
		int x=(int)(str[i]-'0');
		node nape2;
		nape2.arr[0][0]=base.arr[0][0];
		nape2.arr[0][1]=base.arr[0][1];
		nape2.arr[1][0]=base.arr[1][0];
		nape2.arr[1][1]=base.arr[1][1];
		while(x) {
			if(x&1) b1=mul(b1,nape2);
			nape2=mul(nape2,nape2);
			x>>=1;
		}
		node nape1=mul(base,base);
		base=mul(base,base);
		base=mul(base,base);
		base=mul(base,base);
		base=mul(nape1,base);
	}
	return b1.arr[0][1]%p;
}
int main() 
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif
    //freopen("out.txt", "w", stdout);
    //ios::sync_with_stdio(0),cin.tie(0); 
    ll x0,x1,a,b;
    scanf("%I64d %I64d %I64d %I64d",&x0,&x1,&a,&b);
    scanf("%s",str);
    scanf("%I64d",&p);
    base.arr[0][0]=a;base.arr[0][1]=1LL;
    base.arr[1][0]=b;base.arr[1][1]=0;
    b1.arr[0][0]=x1;b1.arr[0][1]=x0;
    b1.arr[1][0]=0;b1.arr[1][1]=0;
    len=strlen(str);
    printf("%I64d\n",quickpow());
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值