zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(五)

    声明:本文章题目来源均为牛客网

    链接:https://ac.nowcoder.com/acm/contest/885#question

    B-generator 1

    题目链接:https://ac.nowcoder.com/acm/contest/885/B

    题目类型:矩阵乘法,矩阵快速幂,十进制快速幂

    题目大意

    给四个正整数 X0,X1,a,b,然后有一个公式 Xi=a*Xi-1+b*Xi-2(i>2),题目给出两个正整数n和mod,然后输出Xn%mod的值,n是一个很大的数。

    (1 < X0,X1,a,b < 1e9),(1e9 < mod <2e9),(2 < n < 1e1e6

    题目理解

    题目给了一个递推式,而且n很大,可以用矩阵来写。化成化成矩阵然后用矩阵快速幂,对于n为1e1e6,用二进制倍增是解决不了问题的,所以要用十进制倍增同时用二进制倍增优化。和二进制快速幂差不多的思想,十进制快速幂犹如将3419拆成31x9 * 310x1 * 3100x4。上个板子应该就好理解了。

    typedef long long ll;
    ll pow2(ll base,ll k,ll mod){//二进制 
        ll ans=1;
        while(k){
            if(k&1) ans=(ans*base)%mod;
            k>>=1;
            base=(base*base)%mod;
        }
        return ans%mod;
    }
    //s为用字符串存放的大数 
    ll pow10(ll base,string s,ll mod){//十进制 
        ll ans=1,res=1;
        ll len=s.size();
        for(int i=len-1;i>=0;i--){
            ll k=s[i]-'0';
            res=pow2(base,k,mod);
            ans=(ans*res)%mod;
            base=pow2(base,10,mod);
        }
        return ans%mod;
    }

    理解了十进制快速幂,那么这题就和普通的矩阵快速幂差不多了。

    AC代码

    //十进制快速幂 
    #include<iostream>
    #include<cstdio>
    #include<string>
    #define ll long long 
    #define sc(x) scanf("%lld",&x);
    using namespace std;
    ll x0,x1,a,b,mod;
    string n;
    struct jz{
        ll sq[2][2];
        jz(){
            sq[0][0]=1ll;sq[0][1]=0ll;sq[1][0]=0ll;sq[1][1]=1ll;
        }
    };
    jz mul(jz j1,jz j2){
        jz ans;
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++){
                ll x=0;
                for(int k=0;k<2;k++)
                    x+=((ll)j1.sq[i][k]*j2.sq[k][j])%mod;
                ans.sq[i][j]=x%mod;
            }
        return ans;
    }
    jz pow2(jz t,ll k){
        jz tt;
        while(k){
            if(k&1) tt=mul(tt,t);
            k>>=1;
            t=mul(t,t);
        }
        return tt;
    }
    jz pow10(jz t){
        jz t1,t2;
        for(int i=n.size()-1;i>=0;i--){
            ll k=n[i]-'0';
            t1=pow2(t,k);
            t2=mul(t2,t1);
            t=pow2(t,10);
        }
        return t2;
    }
    int main(){
        sc(x0);sc(x1);sc(a);sc(b);cin >> n;sc(mod);
        x1%=mod;x0%=mod;
        for(int i=n.size()-1;i>=0;i--){
            if(n[i]=='0')
                n[i]='9';
            else{
                n[i]=char(n[i]-1);break;
            }
        }
        jz t;
        t.sq[0][0]=a;t.sq[0][1]=1;t.sq[1][0]=b;t.sq[1][1]=0;
        t=pow10(t);
        printf("%lld",((t.sq[0][0]*x1)%mod+(t.sq[1][0]*x0)%mod)%mod);
        return 0;
    }

    后记

    这道题不难。不知道10进制快速幂的话就另说。

  • 相关阅读:
    什么是page fault?
    [转载] 使用 Docker 部署 openstf 平台
    dockerfile中设置python虚拟环境+gunicorn启动
    python虚拟环境
    appium 多设备
    jenkins初始化和安装插件
    安装docker-ce
    Seleium Grid配置中的MaxInstances和MaxSession详解
    【GIS】GeoServer-Cache
    【GIS】GeoServer-服务权限
  • 原文地址:https://www.cnblogs.com/lastonepersonwhohavebitenbycompanies/p/11288719.html
Copyright © 2011-2022 走看看