19年牛客暑期多校训练营第五场 B-generator 1 (十进制矩阵快速幂)

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

题目描述

You are given four positive integers x0,x1,a,bx_0, x_1, a, bx0​,x1​,a,b. And you know xi=a⋅xi−1+b⋅xi−2x_i = a \cdot x_{i-1} + b \cdot x_{i-2}xi​=a⋅xi−1​+b⋅xi−2​ for all i≥2i \ge 2i≥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!

输入描述:

The input contains two lines.
The first line contains four integers x0,x1,a,bx_0, x_1, a, bx0​,x1​,a,b (1≤x0,x1,a,b≤1091 \le x_0, x_1, a, b \le 10^91≤x0​,x1​,a,b≤109).
The second line contains two integers n, MOD (1≤n<10(106),109<MOD≤2×1091 \le n < 10^{(10^6)}, 10^9 < MOD \le 2 \times 10^91≤n<10(106),109<MOD≤2×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

 解题思路:十进制矩阵快速幂。答案为矩阵{{a,b}{1,0}}的n-1次方。

十进制快速幂可参考:Here

/*
@Author: Top_Spirit
@Language: C++
*/
#include <bits/stdc++.h>
using namespace std ;
typedef unsigned long long ull ;
typedef long long ll ;
const int Maxn = 1e3 + 10 ;
const int INF = 0x3f3f3f3f ;
const double PI = acos(-1.0) ;
const ull seed = 133 ;
const int MOD = 51123987 ;

struct Node {
    ll mat[2][2] ;
}ans, tmp, O, z ;

ll x0, x1, a, b ;
ll mod, len ;
string n ;

void init(){
    ans.mat[0][0] = ans.mat[1][1] = 1 ;
    ans.mat[0][1] = ans.mat[1][0] = 0 ;
    tmp.mat[0][0] = a ;
    tmp.mat[0][1] = b ;
    tmp.mat[1][0] = 1 ;
    tmp.mat[1][1] = 0 ;
}

Node getPow(Node a, Node b){
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++){
            z.mat[i][j] = 0 ;
            for (int k = 0; k < 2; k++){
                z.mat[i][j] = (z.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % mod ;
            }
        }
    }
    return z ;
}

int main (){
    ios_base::sync_with_stdio(false) ;
    cin.tie(0) ;
    cout.tie(0) ;
    cin >> x0 >> x1 >> a >> b ;
    cin >> n >> mod ;
    len = n.size() ;
    len-- ;
    init() ;
    for (int i = len; i >= 0; i--) {
        ll cnt = n[i] - '0' ;
        for (int i = 1; i <= cnt; i++) ans = getPow(ans, tmp) ;
        O.mat[0][0] = O.mat[1][1] = 1 ;
        O.mat[0][1] = O.mat[1][0] = 0 ;
        for (int j = 0; j < 10; j++) O = getPow(O, tmp) ;
        tmp = O ;
    }
    cout << (x1 * ans.mat[1][0] + x0 * ans.mat[1][1]) % mod << endl ;
    return 0 ;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值