2019牛客ACM多校赛第5场 generator 1

链接:https://ac.nowcoder.com/acm/contest/885/B
来源:牛客网
 

You are given four positive integers x0,x1,a,b. And you know xi=a⋅xi−1+b⋅xi−2 for all i≥2 .

Given two positive integers n, and MOD, please calculate xnx_nxn​ modulo MOD.

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

题意:

很简单,给你有关xi的递推公式和a,b,x0,x1,求出xn

输入描述:

The input contains two lines.
The first line contains four integers x0,x1,a,b (1≤x0​,x1​,a,b≤10^9).
The second line contains two integers n, MOD (1≤n<10^(10^6),10^9<MOD≤2×10^9, 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

思路:

一看到xi=a⋅xi−1+b⋅xi−2,并且给你初值,求xn,马上就想到了矩阵快速幂,但是快速幂以2为单位,n<10^(10^6),long long 都读不进n,赛后看题解和别人代码,豁然开朗,快速幂以10为单位,n用字符串存储,可以方便得解决这题。以10为单位解法具体看代码

求快速幂用的矩阵

PS:虽然(x0,x1)是1*2的矩阵,但是为了方便与2*2的A相乘,(x0,x1)也设置为2*2的矩阵((x0,x1),(0,0))

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX=2e9;
ll x0,x1,a,b,mod;
string n;
struct matrix{
	ll a[2][2];
	void init0() { a[0][0]=a[0][1]=a[1][0]=a[1][1]=0; }
	void init1() { a[0][1]=a[1][0]=0; a[0][0]=a[1][1]=1; }//初始化为单位矩阵 
	void init(int x0,int y0,int x1,int y1){
		a[0][0]=x0; a[0][1]=y0; a[1][0]=x1; a[1][1]=y1;
	}	
	matrix operator * (const matrix& b) {
		matrix res; res.init0();
		res.a[0][0] = (a[0][0] * b.a[0][0] + a[0][1] * b.a[1][0]) % mod ;
		res.a[0][1] = (a[0][0] * b.a[0][1] + a[0][1] * b.a[1][1]) % mod ;
		res.a[1][0] = (a[1][0] * b.a[0][0] + a[1][1] * b.a[1][0]) % mod ;
		res.a[1][1] = (a[1][0] * b.a[0][1] + a[1][1] * b.a[1][1]) % mod ;
		return res;
	}
};
matrix ten(matrix A){
	matrix t2 = A * A;//A的平方
	matrix t4 = t2 * t2;//四次 
	matrix t8 = t4 * t4;//8次 
	return t8 * t2 ; //返回10次 
}
matrix pow(matrix A,string& n){//矩阵快速幂,以10为单位 
	matrix res; res.init1();
	for(int i=n.length()-1;i>=0;i--){
		int num=n[i]-'0';
		while(num--) res = res * A; //res*num个A
		A = ten(A); //下一位的数,每一个就是以A^10为单位 
	}
	return res;
}
int main()
{  
    cin>>x0>>x1>>a>>b>>n>>mod;
    matrix xx,y;
    xx.init(x0,x1,0,0); y.init(0,b,1,a);
    y = pow(y,n);
    xx = xx * y;
    printf("%lld\n",xx.a[0][0]);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值