zoukankan      html  css  js  c++  java
  • [Luogu] P4838 P哥破解密码

    题目背景

    P哥是一个经常丢密码条的男孩子。

    在ION 8102赛场上,P哥又弄丢了密码条,笔试满分的他当然知道这可是要扣5分作为惩罚的,于是他开始破解ION Xunil系统的密码。

    题目描述

    定义一个串合法,当且仅当串只由A和B构成,且没有连续的3个A。P哥知道,密码就是长度为N的合法字符串数量对19260817取模的结果。但是P哥不会算,所以他只能把N告诉你,让你来算

    至于为什么要对这个数取模,好像是因为纪念某个人,但到底是谁,P哥也不记得了

    然而他忘记字符串长度N应该是多少了,于是他准备试M组数据。

    题目解析

    WA了两次。

    递推题,在长度为n-1的合法串中有这几种:末尾有连续2个A,末尾有1个A,末尾不是A。

    然后稍加思考就可以发现在长度为n的串中末尾连续2个A的可以由长度为n-1的合法串中末尾是1个A的得到。

    类似的,末尾一个A的可以由末尾没有A的得到,末尾是B的能由所有状态得到。

    所以我们构造出下面的矩阵三行分别表示末尾是B,末尾1个A,末尾2个A。

    1,1,1

    1,0,0

    0,1,0

    矩阵快速幂+取模即可。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    const long long p = 19260817;
    
    struct Matrix {
        long long m[10][10];
        long long sizx,sizy;
        void reset() {
            for(int i = 1;i <= sizx;i++) {
                for(int j = 1;j <=sizy;j++) {
                    if(i == j) m[i][j] = 1;
                    else m[i][j] = 0;
                }
            }
            return;
        }
        void clean() {
            memset(m,0,sizeof(m));
            return;
        }
    } pro;
    
    int T;
    long long n,ans;
    /*
    1,1,1
    1,0,0
    0,1,0
    */
    inline void init() {
        pro.sizx = 3, pro.sizy = 3;
        pro.clean();
        pro.m[1][1] = pro.m[1][2] = pro.m[1][3] = pro.m[2][1] = pro.m[3][2] = 1;
        return;
    }
    
    inline Matrix mul(Matrix x,Matrix y) {
        Matrix res;
           res.clean();
        res.sizx = x.sizx, res.sizy = y.sizy;
        for(register int i = 1;i <= x.sizx;i++) {
            for(register int j = 1;j <= y.sizy;j++) {
                for(register int k = 1;k <= x.sizy;k++) {
                    res.m[i][j] += x.m[i][k] * y.m[k][j] % p;
                    res.m[i][j] %= p;
                }
            }
        }
        return res;
    }
    
    inline Matrix quick_pow(Matrix x,long long y) {
        Matrix res;
        res.sizx = x.sizx; res.sizy = x.sizy;
        res.reset();
        while(y) {
            if(y & 1) res = mul(res,x);
            x = mul(x,x);
            y >>= 1;
        }
        return res;
    }
    
    int main() {
        scanf("%d",&T);
        while(T--) {
            scanf("%lld",&n);
            if(n == 1) {puts("2");continue;}
            else if(n == 2) {puts("4");continue;}
            else if(n == 3) {puts("7");continue;}
            init();
            Matrix final = quick_pow(pro,n);
            printf("%lld
    ",(final.m[1][1]+final.m[1][2])%p);
        }
        return 0;
    }
  • 相关阅读:
    Jquery学习系列-制作Menu
    关于javascript里的parseInt() 与 parseFloaat() 文本转换为数字
    javascript简述
    【代码片段】HTML5基本结构及常用默认模版
    赋值运算符
    【代码片段】jQuery实现页面滚动时层智能浮动定位Fixed Floating Elements
    【代码片段】formLogin
    算数运算符
    关于javascript里的toFixed()方法格式化数字
    关于javascript里的setTimerout()设定时间
  • 原文地址:https://www.cnblogs.com/floatiy/p/9842494.html
Copyright © 2011-2022 走看看