CF-Codeforces Round #420 (Div. 2)-E-Okabe and El Psy Kongroo

来源:互联网 发布:diner dash 5 mac 编辑:程序博客网 时间:2024/05/08 03:38

ACM模版

描述

描述
描述

题解

这个题是矩阵快速幂问题,给定若干个上界,每个上界都是有一定宽度的,这些上界在 x 轴的投影是连续的,要我们从 (0,0) 移动到 (k,0),每次只能向右、右上、右下移动,所以呢,这个其实和 《机器人走方格》有些相似,不过他是给定了连续的若干个矩形区域(每个上界和 x 轴之间的区域),需要求这些区域合并在一起后的方案数,另外这里我们的 k 是很大的,所以必须使用矩阵快速幂了。

因为上界最大为 15,所以我们需要构造一个 1616 的矩阵进行快速幂,这个矩阵的样子大概是酱紫的:

A=1100000111000001110000011000000011000001110000011

这也是本题的核心,构造出来这个矩阵,也就好写多了……

剩下的就看看代码吧,没有什么稀奇古怪的了,注意数据类型。

代码

#include <cstdio>#include <cstring>#define mod(x) ((x) % MOD)using namespace std;typedef long long ll;const ll MOD = 1e9 + 7;const int MAX_MAT_SIZE = 16;typedef struct Matrix{    ll m[MAX_MAT_SIZE][MAX_MAT_SIZE];} mat;mat A, B, pre, unit;mat matrix_mul(mat a, mat b, int len){    mat ret;    memset(ret.m, 0, sizeof(ret.m));    for (int k = 0; k <= len; k++)    {        for (int i = 0; i <= len; i++)        {            if (a.m[i][k])            {                for (int j = 0; j <= len; j++)                {                    ret.m[i][j] = mod(ret.m[i][j] + (ll)a.m[i][k] * b.m[k][j]);                }            }        }    }    return ret;}void init(){    memset(A.m, 0, sizeof(A.m));    for (int i = 0; i < MAX_MAT_SIZE; i++)    {        for (int j = i - 1; j < i + 2 && j < MAX_MAT_SIZE; j++)        {            if (j >= 0)            {                A.m[i][j] = 1;            }        }    }    memset(unit.m, 0, sizeof(unit.m));    for (ll i = 0; i < MAX_MAT_SIZE; i++)    {        unit.m[i][i] = 1;    }    memset(pre.m, 0, sizeof(pre.m));    pre.m[0][0] = 1;}Matrix matrix_quick_power(mat a, ll k, int len){    mat ret = unit;    while (k)    {        if (k & 1)        {            ret = matrix_mul(a, ret, len);        }        a = matrix_mul(a, a, len);        k >>= 1;    }    return ret;}int n;ll k;int main(){    init();    scanf("%d%lld", &n, &k);    ll a, b;    int c, flag = 0;    for (int i = 1; i <= n; i++)    {        scanf("%lld%lld%d", &a, &b, &c);        if (b > k)        {            b = k;            flag = 1;        }        B = matrix_quick_power(A, b - a, c);        for (int j = c + 1; j < MAX_MAT_SIZE; j++)        {            pre.m[j][0] = 0;        }        B = matrix_mul(B, pre, c);        for (int j = 0; j <= c; j++)        {            pre.m[j][0] = B.m[j][0];        }        if (flag == 1)        {            break;        }    }    printf("%lld\n", B.m[0][0]);    return 0;}
阅读全文
0 0
原创粉丝点击