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;
}

 

posted @ 2018-04-21 11:59  Zoez  阅读(170)  评论(0编辑  收藏  举报