2018ICPC焦作- Poor God Water 求递推式+矩阵快速幂

题目链接:https://nanti.jisuanke.com/t/31721

题意:一个孩子吃饭,有meat, fish 和 chocolate 三种食物可以选。要求连续三顿饭食物不能完全相同,鱼和肉的前一顿和后一顿不能都是巧克力,巧克力的左右两边不能同时出现鱼和肉。

思路:分九种情况,求出递推式,写出标准矩阵,用矩阵快速幂。

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#define maxn 10000000009
#define MOD    1000000007
#define ll long long
using namespace std;

ll jz[10][10] = { {0, 0,0,0,0,0,0,0,0,0},
                {0, 0,0,0,1,0,0,1,0,0},
                {0, 1,0,0,0,0,0,1,0,0},
                {0, 1,0,0,1,0,0,1,0,0},
                {0, 0,1,0,0,1,0,0,0,0},
                {0, 0,1,0,0,0,0,0,1,0},
                {0, 0,0,0,0,1,0,0,1,0},
                {0, 0,0,1,0,0,1,0,0,1},
                {0, 0,0,1,0,0,0,0,0,1},
                {0, 0,0,1,0,0,1,0,0,0} };
struct juzhen {
    ll a[10][10];
}arr[35];
ll n, t;

void mulmod(ll a, ll b, ll &c) {
    ll a1, a2, b1, b2;
    a1 = a >> 1;
    a2 = a - a1;
    b1 = b >> 1;
    b2 = b - b1;

    c += (a1*b1) % MOD ;
    c %= MOD;
    c += (a1*b2) % MOD;
    c %= MOD;
    c += (a2*b1) % MOD;
    c %= MOD;
    c += (a2*b2) % MOD;
    c %= MOD;
}

void jzxjz(juzhen x, juzhen y, juzhen &jieguo) {
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= 9; j++) {
            jieguo.a[i][j] = 0;
            for (int k = 1; k <= 9; k++) {
                mulmod(x.a[i][k], y.a[k][j], jieguo.a[i][j]);
            }
        }
    }
}

int findmax(int l,int r,ll n) { //不要递归,会超时
    int mid;
    while (r-l>1)
    {
        mid = (l + r) >> 1;
        mid++;
        if (n >= 1ll << mid) {
            l = mid;
        }
        else r = mid - 1;
    }
    return l;
}

void muljz(ll n, juzhen &jzn) {
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= 9; j++) {
            jzn.a[i][j] = !(j ^ i);
        }
    }

    int k;
    while (n>0)
    {
        k = findmax(0, 34, n);
        jzxjz(jzn, arr[k], jzn);
        n -= 1ll << k;
    }
}
void setarr() {  //arr[k] 代表初始矩阵的2^k次幂
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= 9; j++) {
            arr[0].a[i][j] = jz[i][j];
        }
    }
    for (int i = 1; i <= 34; i++) {
        jzxjz(arr[i - 1], arr[i - 1], arr[i]);
    }
}
int main()
{
    setarr();
    juzhen jzn1;
    ll ans;

    scanf("%lld", &t);
    while (t--) {
        scanf("%lld", &n);
        if (n == 2) {
            printf("%d\n", 9);
            continue;
        }
        if (n == 1) {
            printf("%d\n", 3);
            continue;
        }

        muljz(n - 2, jzn1);
        ans = 0;
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                ans += jzn1.a[i][j];
                ans %= MOD;
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/the-way-of-cas/p/9683450.html

时间: 2024-09-29 10:56:41

2018ICPC焦作- Poor God Water 求递推式+矩阵快速幂的相关文章

[题解][SHOI2013]超级跳马 动态规划/递推式/矩阵快速幂优化

这道题... 让我见识了纪中的强大 这道题是来纪中第二天(7.2)做的,这么晚写题解是因为 我去学矩阵乘法啦啦啦啦啦对矩阵乘法一窍不通的童鞋戳链接啦 层层递推会TLE,正解矩阵快速幂 首先题意就是给你一个 n 行m 列 的格子图 一只马从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行. 题意很简单暴力dp的思路也很简单但是数据很恶心虽然远古一点,但毕竟是省选题 1 ≤ n ≤ 50,2 ≤ m ≤ 10^9 不过还是给了我们一点提示:n这么小? 总之我们先找出转移式对于每一个点

hihoCoder 1143 : 骨牌覆盖问题&#183;一(递推,矩阵快速幂)

[题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘.对于这个棋盘,一共有多少种不同的覆盖方法呢? 举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式: 提示:骨牌覆盖 提示:如何快速计算结果 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 M

「常系数齐次线性递推」——矩阵快速幂的优化

引入: 对于递推方程: $$F(x) = \sum_{i=1}^k a_iF(x-i)$$ 我们显然会得到一个关于$F$的多项式求逆或者矩阵递推式,大多数情况下我们都是用后者,但是当$k$很大的时候,$k^3log n$的时间复杂度我们是吃不消的,那么自然我们的前人就搞出了一些优化. 特征多项式及Cayley-Hamilton定理: 一.特征多项式的定义: 设$A$是$n$阶矩阵,若数$\lambda$和非零列向量$x$使关系式$$Ax=\lambda x\;\;\;\;\;(1)$$ 成立,那

[HDOJ2604]Queuing(递推,矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2604 递推式是百度的,主要是练习一下如何使用矩阵快速幂优化. 递推式:f(n)=f(n-1)+f(n-3)+f(n-4),其中f(0)=2, f(1)=4, f(2)=6, f(3)=9. 当n>4时候,需要通过这个关系来递推. 构造矩阵这种东西我以前一直认为是很玄学的,但是如果深入研究的话不难发现其实也有规律可循.这是一个齐次递推式,很好构造. 我们希望通过如下矩阵(1)得到矩阵(2) | f(n

10.02 T3 打表找递推式+十进制快速幂 九校联考凉心模拟DAY1T1

题目背景 金企鹅同学非常擅长用1*2的多米诺骨牌覆盖棋盘的题.有一天,正 在背四六级单词的他忽然想:既然两个格子的积木叫“多米诺(domino)”,那 么三个格子的的积木一定叫“三米诺(tromino)”了!用三米诺覆盖棋盘的题 怎么做呢? 题目描述 用三米诺覆盖3n 的矩形棋盘,共多少种方案?三米诺可旋转:两种 方案不同当且仅当这两种图案直接覆盖在一起无法重叠. 输入输出格式 输入格式: 一行一个整数n(n<=10^40000),表示棋盘列数. 输出格式: 一行一个整数,表示方案数,对9982

hdu2604 递推转换矩阵快速幂

刚开始还以为用位运算与或几下几个循环就搞定了,算着算着发现不行........ 还是一种固定的切题角度,我假设有长度为n,总的排列数位f(n),怎么算他呢?从后往前考虑,因为大多数情况,都是用前面的结果推后面的结果, 那么当第n位是m的时候,如果我知道f(n-1)等于多少,那么f(n-1)的排列+加一个m是不是就是f(n)的一部分解了?  对吧,以此类推,   当第n位为f的时候,可是fff,fmf不能连着 那是不是就剩下ffm,fmm的情况了,对于前者ffm,由于不能凑成ffmf的情况,所以只

hiho 1143 矩阵快速幂 求递推式

题目链接: hihocoder 1143 思路见题目上 快速幂模板: // m^n % k int quickpow(int m,int n,int k) { int b = 1; while (n > 0) { if (n & 1) b = (b*m)%k; n = n >> 1 ; m = (m*m)%k; } return b; } 题解: #include<iostream> #include<cstdio> #include<cstring

ACM学习历程—SNNUOJ 1110 A Simple Problem(递推 &amp;&amp; 逆元 &amp;&amp; 组合数学 &amp;&amp; 快速幂)(2015陕西省大学生程序设计竞赛K题)

Description Assuming a finite – radius “ball” which is on an N dimension is cut with a “knife” of N-1 dimension. How many pieces will the “ball” be cut into most?However, it’s impossible to understand the following statement without any explanation.L

2016 pku campusH/OpenJ_POJ - C16H(推公式+矩阵快速幂)

传送门:http://poj.openjudge.cn/practice/C16H?lang=en_US 题面:描述 Wenwen has a magical ball. When put on an infinite plane, it will keep duplicating itself forever. Initially, Wenwen puts the ball on the location (x0, y0) of the plane. Then the ball starts