zoukankan      html  css  js  c++  java
  • HDU 6030 Happy Necklace

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=6030

    题意:给出红蓝两种,然后排成一个字符串,要求在每一个长度为素数的区间里面是的r(red)的数量不小与b(blue)的数量;

    解法:难点在于如何找规律。容易推知只要长度为2或3的字符串满足r>=b,那么之后的素数(5、7......)都会满足r>=b。

    假设现在有一个n字符的串,其方案数为f(n),考虑一下能否从f(n-1)推得f(n)?

    情况1.如果这个串最后一个字符是r,那么倒数第二个既可以是r也可以是b。所以此时f(n) = f(n-1).

    情况2.如果这个串最后一个字符是b,那么倒数第二个一定是r才可以满足“长度为2且r>=b”的条件,那么倒数第三个就一定是r,否则不满足“长度为3且r>=b”的条件。所以此时f(n) = f(n-3)

    综上,可得f(n) = f(n-1) + f(n-3).

    由于输入量巨大(1018),所以用数组储存递推结果是不可行的,而每次递推又太慢,所以只能用矩阵快速幂来解决。

    由于递推式中出现f(n-3),所以传递矩阵一定是3*3的。

    经过推导可得传递矩阵为

    1 1 0

    0 0 1

    1 0 0

    AC:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const ll m = 1000000000+7;
    const int N = 4;
    struct mar
    {
        ll a[N][N];
    };//结构化矩阵
    
    mar mul(mar x,mar y)
    {
        mar temp;
        for(int i = 1 ; i < N ; i++)
            for(int j = 1 ; j < N ; j++)
            temp.a[i][j] = 0;
        for(int i = 1 ; i < N ; i++)
            for(int j = 1 ; j < N ; j++)
                    for(int k = 1 ; k < N ; k++)
                        temp.a[i][j] += (x.a[i][k]%m*y.a[k][j]%m)%m;
        return temp;
    }//矩阵乘法
    
    mar quickpow(mar a,ll n)
    {
        mar res;
        res.a[1][1] = 1; res.a[1][2] = 0; res.a[1][3] = 0;
        res.a[2][1] = 0; res.a[2][2] = 1; res.a[2][3] = 0;
        res.a[3][1] = 0; res.a[3][2] = 0; res.a[3][3] = 1;//初始化为单位矩阵
        while(n)
        {
            if(n&1) res = mul(res,a);
            a = mul(a,a);
            n>>=1;
        }
        return res;
    }//矩阵快速幂核心代码
    
    int main()
    {
        int t;
        ll n;
        cin >> t;
        while(t--)
        {
            cin >> n;
            if(n==2) {cout << 3 <<endl;continue;}
            mar A;
            A.a[1][1] = 1; A.a[1][2] = 0; A.a[1][3] = 1;
            A.a[2][1] = 1; A.a[2][2] = 0; A.a[2][3] = 0;
            A.a[3][1] = 0; A.a[3][2] = 1; A.a[3][3] = 0;//构造传递矩阵
            mar res = quickpow(A,n-2);
            cout <<  ((res.a[1][1] + res.a[1][2] + res.a[1][3]) % m+ (res.a[2][1] + res.a[2][2] + res.a[2][3]) % m+(res.a[3][1] + res.a[3][2] + res.a[3][3]) % m)%m <<endl;
        }
        return 0;
    }
  • 相关阅读:
    BZOJ 2588
    BZOJ 3524
    BZOJ 3932
    Bzoj1013--Jsoi2008球形空间产生器
    Codevs1743--反转卡片
    Bzoj1208--Hnoi2004宠物收养所
    Bzoj1112--Poi2008砖块Klo
    后缀自动机学习笔记
    Bzoj1588--Hnoi2002营业额统计
    Bzoj1056--Haoi2008排名系统
  • 原文地址:https://www.cnblogs.com/zz990728/p/8886380.html
Copyright © 2011-2022 走看看