码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-09-20 21:52:18      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:clu   set   ios   初始   com   dma   scanf   标准   bsp   

题目链接: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;
}

 

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

标签:clu   set   ios   初始   com   dma   scanf   标准   bsp   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!