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

2016-2017 ACM-ICPC Asia-Bangkok Regional Contest

时间:2018-06-03 17:33:23      阅读:433      评论:0      收藏:0      [点我收藏+]

标签:using   lld   nal   pac   splay   algo   sizeof   for   注意   

G:矩阵快速幂

首先找规律,发现数量规律是一个斐波拉契数列,长度为k的串,长度为f(k+1)。之后求[L,R]区间内的和,于是可以想到利用矩阵快速幂求前缀和,将2*2的斐波拉契数列系数矩阵增加一维求和。注意初始的是f(k+1)。所以构造矩阵有一些奇特(见代码)

技术分享图片
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
const long long mod = 1e9 + 7;
struct Matrix
{
    long long data[35][35];
    int col, row;
    Matrix() {}
    Matrix(int _row, int _col)
    {
        row = _row;
        col = _col;
        memset(data, 0, sizeof(data));
    }
    const long long * operator [] (int row) const         //жидиЯТБъдЫЫуЗ?
    {
        return data[row];
    }
    long long * operator [] (int row)
    {
        return data[row];
    }
};
Matrix operator * (const Matrix &m1, const Matrix &m2)
{
    Matrix ans_met(m1.row, m2.col);
    int i, j, k;
    for (i = 0; i < m1.row; i++)
    {
        for (j = 0; j < m2.col; j++)
        {
            for (k = 0; k < m1.col; k++)
            {
                ans_met[i][j] = (ans_met[i][j] + (m1[i][k] * m2[k][j]) % mod) % mod;
            }
        }
    }
    return ans_met;
}
Matrix operator ^(const Matrix &mm, long long q)
{
    Matrix ans_met(mm.row, mm.col);
    Matrix ret(mm.row, mm.col);
    int i, j;
    for (i = 0; i < ans_met.row; i++)
    {
        for (j = 0; j < ans_met.col; j++) ret[i][j] = mm[i][j];
        ans_met[i][i] = 1;
    }
    while (q > 0)
    {
        if (q % 2 == 1) ans_met = ans_met * ret;
        ret = ret * ret;
        q /= 2;
    }
    return ans_met;
}
Matrix operator + (const Matrix &m1, const Matrix &m2)
{
    Matrix ans_met(m1.row, m2.col);
    int i, j;
    for (i = 0; i < m1.row; i++)
    {
        for (j = 0; j < m1.col; j++)
        {
            ans_met[i][j] = (m1[i][j] + m2[i][j]) % mod;
        }
    }
    return ans_met;
}

Matrix fab(2, 2), mat(3, 3);

long long solve(long long q)
{
    q++;              //注意要移位
    Matrix tmp(3, 3);
    tmp = mat ^ q;
    return tmp[0][2]-1;
}

int main()
{
    int i, j;
    int t;
    scanf("%d", &t);
    int cases = 1;
    while (t--)
    {
        long long l, r, k;
        scanf("%lld%lld%lld", &l, &r, &k);
        if (l%k != 0) l += k - (l%k);      //处理余数
        if (r%k != 0) r -= r % k;
        fab[0][0] = 1;
        fab[0][1] = 1;
        fab[1][0] = 1;
        fab[1][1] = 0;
        fab = fab ^ k;

        mat[0][0] = fab[0][0];         //构造求和矩阵
        mat[0][1] = fab[0][1];
        mat[1][0] = fab[1][0];
        mat[1][1] = fab[1][1];
        mat[0][2] = 1;
        mat[1][2] = 1;
        mat[2][0] = 0;
        mat[2][1] = 0;
        mat[2][2] = 1;
        long long le = solve(l / k - 1), ri = solve(r / k);
        long long ans = ((ri - le) % mod + mod) % mod;
        printf("Case %d: ", cases++);
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

2016-2017 ACM-ICPC Asia-Bangkok Regional Contest

标签:using   lld   nal   pac   splay   algo   sizeof   for   注意   

原文地址:https://www.cnblogs.com/Hetui/p/9129577.html

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