天天写算法之HDU 2604 Queuing

膜拜一波大神代码

分析:矩阵快速幂

题目地址:HDU 2604 Queuing

题意: 
n个人排队,f表示女,m表示男,包含子串‘fmf’和‘fff’的序列为O队列,否则为E队列,有多少个序列为E队列

: 
矩阵快速幂入门题。 


用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1); 
如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf, fmf, mff, fff,其中fff和fmf不满足题意所以我们不考虑,但是如果是 
mmf的话那么前n-3可以找满足条件的即:f(n-3);如果是mff的话,再往前考虑一位的话只有mmff满足条件即:f(n-4) 
所以f(n)=f(n-1)+f(n-3)+f(n-4),递推会跪,可用矩阵快速幂 
构造一个矩阵: 
pic

矩阵快速幂和普通的快速幂原理是一样的,如果不懂可以先去补补快速幂。

#include <cstdio>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
using namespace std;  
#include <cmath>  
#include <cstdlib>  
#define repf(i,a,b) for(int i=(a);i<=(b);i++)  
typedef long long ll;  
  
const int N = 0;  
const int SIZE = 4;  
  
int l, MOD;  
  
struct Mat{  
    ll v[SIZE][SIZE];   // value of matrix  
  
    Mat() {  
        memset(v, 0, sizeof(v));  
    }  
  
    void init(ll _v) {  
        repf (i, 0, SIZE)  
            v[i][i] = _v;  
    }  
};  
  
Mat operator * (Mat a, Mat b) {  
    Mat c;  
    repf (i, 0, SIZE - 1) {  
        repf (j, 0, SIZE - 1) {  
            c.v[i][j] = 0;  
            repf (k, 0, SIZE - 1) {  
                c.v[i][j] += (a.v[i][k] * b.v[k][j]) % MOD;  
                c.v[i][j] %= MOD;  
            }  
        }  
    }  
    return c;  
}  
  
Mat operator ^ (Mat a, ll k) {  
    Mat c;  
    c.init(1);  
    while (k) {  
        if (k&1) c = a * c;  
        a = a * a;  
        k >>= 1;  
    }  
    return c;  
}  
  
int main() {  
    Mat a, b, c;  
    // a  
    a.v[0][0] = 9;  
    a.v[1][0] = 6;  
    a.v[2][0] = 4;  
    a.v[3][0] = 2;  
      
    // b  
    b.v[0][0] = b.v[0][2] = b.v[0][3] = b.v[1][0] = b.v[2][1] = b.v[3][2] = 1;  
  
    while (~scanf("%d%d", &l, &MOD)) {  
        if (l == 0) {  
            puts("0");  
        } else if (l <= 4) {  
            printf("%lld\n", a.v[4 - l][0] % MOD);  
        } else {  
            c = b ^ (l - 4);  
            c = c * a;  
            printf("%lld\n", c.v[0][0] % MOD);  
        }  
    }  
  
    return 0;  
}  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值