HDU——4291A Short problem(矩阵快速幂+循环节)

A Short problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2461    Accepted Submission(s): 864

Problem Description

  According to a research, VIM users tend to have shorter fingers, compared with Emacs users.
  Hence they prefer problems short, too. Here is a short one:
  Given n (1 <= n <= 1018), You should solve for 
g(g(g(n))) mod 109 + 7
  where
g(n) = 3g(n - 1) + g(n - 2)
g(1) = 1
g(0) = 0

Input

  There are several test cases. For each test case there is an integer n in a single line.
  Please process until EOF (End Of File).

Output

  For each test case, please print a single line with a integer, the corresponding answer to this case.

Sample Input

0
1
2

Sample Output

0
1
42837

三层复合函数。写完交上去TLE,不解。查了题解发现有循环节。循环节的话用set::find函数来查找是否存在过,若存在则输出循环节,不存在则插入当前数值继续循环。

然后就是矩阵快速幂了。递推式:(当某一层n为0的时候加上mod否则可能出错)

代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
const long long mod=1000000007;
struct mat
{
    LL pos[2][2];
    mat(){memset(pos,0,sizeof(pos));}
};
inline mat mul(const mat &a,const mat &b,const LL &mod)
{
    mat c;
    for (int i=0; i<2; i++)
    {
        for (int j=0; j<2; j++)
        {
            for (int k=0; k<2; k++)
            {
                c.pos[i][j]+=((a.pos[i][k])%mod*(b.pos[k][j])%mod)%(mod);
            }
        }
    }
    return c;
}
inline mat matpow(mat a,LL b,const LL &mod)
{
    mat r;
    r.pos[1][1]=r.pos[0][0]=1;
    mat bas=a;
    while (b!=0)
    {
        if(b&1)
            r=mul(r,bas,mod);
        bas=mul(bas,bas,mod);
        b>>=1;
    }
    return r;
}
int main(void)
{
    mat one,t;
    LL n,ans;
    one.pos[0][0]=1;
    one.pos[0][1]=0;
    t.pos[0][0]=3;
    t.pos[0][1]=t.pos[1][0]=1;
    mat poww,initt;
    while (cin>>n)
    {
        if(n==0)
        {
            cout<<"0"<<endl;
            continue;
        }
        poww=t,initt=one;
        poww=matpow(poww,n-1,183120);
        initt=mul(initt,poww,183120);
        ans=initt.pos[0][0];
        ans+=183120;

        poww=t,initt=one;
        poww=matpow(poww,ans-1,222222224);
        initt=mul(initt,poww,222222224);
        ans=initt.pos[0][0];
        ans+=222222224;

        poww=t,initt=one;
        poww=matpow(poww,ans-1,1000000007);
        initt=mul(initt,poww,1000000007);
        cout<<initt.pos[0][0]%1000000007<<endl;
    }
    return 0;
}
时间: 2024-10-10 02:18:25

HDU——4291A Short problem(矩阵快速幂+循环节)的相关文章

HDU 4291 A Short problem(矩阵快速幂+循环节)

题目链接": http://acm.hdu.edu.cn/showproblem.php?pid=4291 题意: g(0)=0,g(1)=1; g(n) = 3g(n - 1) + g(n - 2): 求g(g(g(n))) mod 109 + 7 分析: 首先我们得认识到,如果一层一层算是必定会超时的. 其次,取模运算是有循环节的. step1我们找出g(x)%1000000007的循环节 mod1 step2 设g(g(n)) = g(x) x=g(n) 对mod1 取模得到mod2. 剩

HDU 2604 Queuing (矩阵快速幂)

HDU 2604 Queuing (矩阵快速幂) ACM 题目地址:HDU 2604 Queuing 题意: n个人排队,f表示女,m表示男,包含子串'fmf'和'fff'的序列为O队列,否则为E队列,有多少个序列为E队列. 分析: 矩阵快速幂入门题. 下面引用巨巨解释: 用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1): 如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf, fmf, mff, fff

HDU 2254 奥运(矩阵快速幂+二分等比序列求和)

HDU 2254 奥运(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 2254 奥运 题意: 中问题不解释. 分析: 根据floyd的算法,矩阵的k次方表示这个矩阵走了k步. 所以k天后就算矩阵的k次方. 这样就变成:初始矩阵的^[t1,t2]这个区间内的v[v1][v2]的和. 所以就是二分等比序列求和上场的时候了. 跟HDU 1588 Gauss Fibonacci的算法一样. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * B

HDU 2604 Queuing,矩阵快速幂

题目地址:HDU 2604 Queuing 题意: 略 分析: 易推出:   f(n)=f(n-1)+f(n-3)+f(n-4) 构造一个矩阵: 然后直接上板子: /* f[i] = f[i-1] + f[i-3] + f[i-4] */ #include<cstdio> #include<cstring> using namespace std; const int N = 4; int L, M; struct mtx { int x[N+1][N+1]; mtx(){ mem

hdu 2243 AC自动机 + 矩阵快速幂

// hdu 2243 AC自动机 + 矩阵快速幂 // // 题目大意: // // 给你一些短串,问在长度不超过k的任意串,包含至少一个这些短串的其中 // 一个.问这样的串有多少个. // // 解题思路: // // 首先, 包含和不包含是一种互斥关系,包含+不包含 = 全集u.全集的答案就是 // 26 ^ 1 + 26 ^ 2 + .... + 26 ^ k.不包含的比较好求.构建一个自动机,得到 // 一个转移矩阵A.表示状态i能到状态j的方法数.而这些状态中都是不包含所给的 //

hdu 1757 A Simple Math Problem 矩阵快速幂

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1757 Lele now is thinking about a simple function f(x).If x < 10 f(x) = x.If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);And ai(0<=i<=9) can only be 0 or 1 .Now, I w

HDU 5950 - Recursive sequence - [矩阵快速幂加速递推][2016ACM/ICPC亚洲区沈阳站 Problem C]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5950 Farmer John likes to play mathematics games with his N cows. Recently, they are attracted by recursive sequences. In each turn, the cows would stand in a line, while John writes two positive numbers

hdu 2604 Queuing(矩阵快速幂乘法)

Problem Description Queues and Priority Queues are data structures which are known to most computer scientists. The Queue occurs often in our daily life. There are many people lined up at the lunch time. Now we define that ‘f’ is short for female and

HDU 5950 Recursive sequence 矩阵快速幂

http://acm.hdu.edu.cn/showproblem.php?pid=5950 一开始以为i^4不能矩阵快速幂,但是结论是可以得,那么要怎么递推呢? 矩阵快速幂的思路都是一样的,matrix_a * matrix_b ^ n 其中,想要维护什么,就在matrix_a写,比如现在是F[n - 1], F[n - 2],我想要递推到下一项,那么就 会变成F[n], F[n - 1],这个时候,你就要寻找一下F[n]和F[n - 1]有什么关系. i^4也一样,想要从i^4 递推到 (i