zoukankan      html  css  js  c++  java
  • 2019牛客多校第五场 B

    B - generator 1

    题意

    给你(x_{0}、x_{1}、a、b、b、mod),根据(x_{i} = a*x_{i-1} + b*x_{i-2})求出(x_{n})

    思路

    一般看到这种题就会想到矩阵快速幂,但是这次的(n)太大了,所以要用十进制倍增来算,但是单单用十进制倍增来算应该还会(TLE),然后就要用二进制倍增来优化了。

    • 我们要先求出矩阵快速幂的通项式

    [egin{pmatrix}x_{n+1} \x_{n}end{pmatrix}= egin{pmatrix}a & b\1& 0 end{pmatrix} egin{pmatrix}x_{n}\ x_{n-1}end{pmatrix}= egin{pmatrix}a & b\1& 0 end{pmatrix}^{n} egin{pmatrix}x_{1}\ x_{0}end{pmatrix}]

    • 用十进制和二进制优化
    for(int i = len-1; i >= 0; i--){
        ans = ans*pow(res, n[i]-'0');
        res = pow(res, 10ll);
    }
    

    (ans = res^{(n[i] - '0')}、(n[i] - '0')):是当前位的数
    (res = res^{10})
    就是把(n)分解成每一位,然后相乘
    例如(a^{300} = (a^{100})^{3}) => (ans = (res^{10})^{n[i]-'0'})
    计算每一位就可以了
    (说的有点混乱,主要是今天突然碰到这种算法很神奇,记录一下~)

    AC代码

    #include<bits/stdc++.h>
    #define mes(a, b) memset(a, b, sizeof a)
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6+10;
    ll mod;
    char n[maxn];
     
    struct Mat{
        ll mat[4][4];
        Mat(){
            mes(mat, 0);
        }
        void init(){
            for(int i = 1; i <= 2; i++)
                mat[i][i] = 1;
        }
     
        Mat operator * (const Mat &a)const{
            Mat ans;
            for(int i = 1; i <= 2; i++){
                for(int j = 1; j <= 2; j++){
                    for(int k = 1; k <= 2; k++){
                        ans.mat[i][j] += mat[i][k]*a.mat[k][j]%mod;
                        ans.mat[i][j] %= mod;
                    }
                }
            }
            return ans;
        }
    };
    
    Mat pow(Mat a, ll b){
        Mat ans;
        ans.init();
        while(b){
            if(b&1)
                ans = ans*a;
            a = a*a;
            b >>= 1;
        }
        return ans;
    }
     
    int main(){
        ll a, b, x1, x0;
        scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
        scanf("%s%lld",n, &mod);
        int len = strlen(n);
        Mat ans; ans.init();
        Mat res;
        res.mat[1][1] = a; res.mat[1][2] = b;
        res.mat[2][1] = 1;
        for(int i = len-1; i >= 0; i--){
            ans = ans*pow(res, n[i]-'0');
            res = pow(res, 10ll);
        }
        Mat f;
        f.mat[1][1] = x1;
        f.mat[2][1] = x0;
        f = ans*f;
        printf("%lld
    ",f.mat[2][1]);
        return 0;
    }
    
  • 相关阅读:
    自动生成四则运算题目
    学习进度总结随笔
    作业1
    软件工程项目总结
    结对编程项目---四则运算
    作业三
    自动生成小学四则运算题目的程序
    学习进度总结
    大三下自我简介
    寒假社会实*报告
  • 原文地址:https://www.cnblogs.com/zhuyou/p/11285849.html
Copyright © 2011-2022 走看看