10.19

#10193 「一本通 6.1 例 1」序列的第 k 个数

3A取模的时候记得全局取模……能取的一定要取

#10195 「一本通 6.1 练习 2」转圈游戏

2A,还是上面的问题,对于转圈圈的问题一定要取模!

#10196 「一本通 6.1 练习 3」越狱

1A快速幂专题是来教你怎么取模的………………注意减法的时候要加上模数再取模


  • 矩乘的n,m,p枚举顺序随便

#10221 「一本通 6.5 例 3」Fibonacci 前 n 项和

如果要维护线性递推式的每一项的和的话,就多加一维,记录前缀和。

状态定义的话:怎么推着舒服怎么来。

注意矩乘没有交换律,在写柿子的时候要慎重!


but,we have 黑科技

S(n)=Fib(n+2)-1

int n,mod;

struct Matrix{
    int m[4][4];
    Matrix(){mem(m,0);}
    friend Matrix operator *(Matrix a,Matrix b){
        Matrix c;
        rep(i,1,3)
            rep(k,1,3)
                rep(j,1,3)
                    c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
        return c;
    }
    friend Matrix operator ^(Matrix a,int k){
        Matrix res;
        rep(i,1,3)res.m[i][i]=1;
        for(;k;k>>=1){
            if(k&1)res=res*a;
            a=a*a;
        }
        return res;
    }
};

#undef int
int main(){
#define int long long
    #ifdef WIN32
    freopen("a.txt","r",stdin);
    #endif
    rd(n),rd(mod);
    Matrix base,ans;
    ans.m[1][1]=1,ans.m[1][2]=1,ans.m[1][3]=1;//sum[1] f[2] f[1]
    base.m[1][1]=1,base.m[1][2]=0,base.m[1][3]=0;
    base.m[2][1]=1,base.m[2][2]=1,base.m[2][3]=1;
    base.m[3][1]=0,base.m[3][2]=1,base.m[3][3]=0;
    base=base^(n-1);
    ans=ans*base;
    printf("%lld
",ans.m[1][1]%mod);
    return 0;
}

P4838 P哥破解密码

首先你得看出这是个线性递推,由上一个状态有多少个A转移而来

范围:1e9的线性递推,那么,上,矩乘!

集合(f[i][j])表示转移到i位字符串,第i位填了j个A的集合的合法个数。

转移

f[i][0]=f[i-1][0]+f[i-1][1]+f[i-1][2];//第i位填B的时候可以由上一位填B,A,AA转移而来
f[i][1]=f[i-1][0]//第i位填A的时候可以由上一位填B转移而来
f[i][2]=f[i-1][1]//第i位填AA的时候可以由上一位填A转移而来
/* 转移矩阵:
1 1 0
1 0 1 
1 0 0
*/ 

终态:f[n][0]+f[n][1]+f[n][2]

初始化

f[1][0]=1,f[1][1]=1,f[1][2]=0;

BTW:求长度为n的字符串的合法个数,那么只需要转移n-1次(因为已经预处理出长度为1的字符串的合法个数)

注意:在base矩阵里面我并没有用到”0“这个角标,以为嫌麻烦。所以所有角标都加上了1的哦

int n;
const int mod=19260817;

struct Matrix {
    int m[4][4];
    Matrix(){mem(m,0);}
    friend Matrix operator *(Matrix a,Matrix b){
        Matrix c;
        rep(i,1,3)
            rep(k,1,3)
                rep(j,1,3)
                    c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
        return c;
    }
    friend Matrix operator ^(Matrix a,int k){
        Matrix res;
        rep(i,1,3)res.m[i][i]=1;
        for(;k;k>>=1){
            if(k&1)res=res*a;
            a=a*a;
        }
        return res;
    }
};

#undef int
int main(){
#define int long long
    #ifdef WIN32
    freopen("a.txt","r",stdin);
    #endif
    int T;rd(T);
    while(T--){
        rd(n);
        Matrix ans,base;
        ans.m[1][1]=1,ans.m[1][2]=1,ans.m[1][3];
        base.m[1][1]=1,base.m[1][2]=1,base.m[1][3]=0;
        base.m[2][1]=1,base.m[2][2]=0,base.m[2][3]=1;
        base.m[3][1]=1,base.m[3][2]=0,base.m[3][3]=0;
        base=base^(n-1);
        ans=ans*base;
        printf("%lld
",(ans.m[1][1]+ans.m[1][2]+ans.m[1][3])%mod);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sjsjsj-minus-Si/p/11704611.html