hdu 5451 Best Solver(矩阵快速幂+循环节)

题意:

已知,给你整数x,和一个素数M,求[y]%M

思路:

(5+2√6)n=Xn+Yn*√6

Xn+Yn*√6 =(Xn-1+Yn-1*√6)*(5+2√6)

=> 5*Xn-1 + 12*Yn-1 + (2*Xn-1 + 5*Yn-1 )*√6

Xn =  5*Xn-1 + 12*Yn-1;

Y=  2*Xn-1 + 5*Yn-1;

然而√6还是一个大问题,解决办法:

(5 - 2√6)= Xn - Yn*√6

(5+2√6)n=Xn+Yn*√6 + X- Yn*√6 - (X- Yn*√6) = 2*Xn - (0.101)n

所以[ (5+2√6)n ]= 2*X- 1

由于n=1+2^x 是一个非常大的数,这时我们要知道广义斐波那契数列的循环节是(MOD-1)*(MOD+1)

代码:

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long

using namespace std;

const int N=2,M=2,P=2;
ll MOD;

struct Matrix
{
    ll m[N][N];
};

Matrix A= {5,12,
           2,5
          };

Matrix I= {1,0,
           0,1
          };

Matrix multi(Matrix a,Matrix b)
{
    Matrix ans;
    for(int i=0; i<N; i++)
    {
        for(int j=0; j<M; j++)
        {
            ans.m[i][j]=0;
            for(int k=0; k<P; k++)
            {
                ans.m[i][j]+=a.m[i][k]*b.m[k][j]%MOD;
            }
            ans.m[i][j]%=MOD;
        }
    }
    return ans;
}

Matrix power(Matrix a,ll k)
{
    Matrix ans=I,p=a;
    while(k)
    {
        if(k&1)
        {
            ans=multi(ans,p);
        }
        k=k/2;
        p=multi(p,p);
    }
    return ans;
}

ll qmod(ll a,ll b,ll mod)
{
    ll ans=1;
    a=a%mod;
    while(b)
    {
        if(b&1)
        {
            ans=(ans*a)%mod;
        }
        b=b/2;
        a=(a*a)%mod;
    }
    return ans;
}

int main(int argc, char const *argv[])
{
    int t,cas=1,n;
    cin>>t;
    while(t--)
    {
        cin>>n>>MOD;
        cout<<"Case #"<<cas++<<": ";
        n=qmod(2,n,(MOD*MOD-1))+1;
        Matrix ans=power(A,n-1);
        ll xn=(5*ans.m[0][0]+2*ans.m[0][1])%MOD;
        cout<<(2*xn-1)%MOD<<endl;
    }
    return 0;
}
时间: 2024-10-27 09:54:58

hdu 5451 Best Solver(矩阵快速幂+循环节)的相关文章

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 5451 Best Solver 矩阵循环群+矩阵快速幂

http://acm.hdu.edu.cn/showproblem.php?pid=5451 题意:给定x    求解 思路: 由斐波那契数列的两种表示方法, 之后可以转化为 线性表示 F[n] = F[n-1] + F[n-2] ; 同时可以看出   和 是 一元二次方程的两根, a  = 1, b = -1 又是之后递推式的系数: 同理这里需要构造出两根为 和 ,这时 a = 1, b = –10 得 F[n] = 10F[n-1] – F[n-2]; (当然可以直接打表递推出关系式) 如果

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

HDU 2842 Chinese Rings(矩阵快速幂+递推)

题目地址:HDU 2842 这个游戏是一个九连环的游戏. 假设当前要卸下前n个环.由于要满足前n-2个都卸下,所以要先把前n-2个卸下,需要f(n-2)次.然后把第n个卸下需要1次,然后这时候要卸下第n-1个,然后此时前n-2个都已经被卸下了.这时候把前n-2个都卸下与都装上所需的次数是一样的,因为卸下与装上的规则是一样的.所以又需要f(n-2)次,这时候前n-1个都在上面,卸下前n-1个需要f(n-1)次. 所以,总共需要2*f(n-2)+f(n-1)+1次. 然后构造如下矩阵. 1,2,1

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 3117 Fibonacci Numbers(矩阵快速幂+公式)

题目地址:HDU 3117 对于后四位可以用矩阵快速幂快速求出来,但前四位就没办法了.要知道斐波那契数列是有通项公式的,所以只能通过通项公式来求前四位,但公式不能求后四位,因为公式使用浮点数求的,精度显然不够,求前四位要用到对数. 通项公式为: f(n)=1/sqrt(5)(((1+sqrt(5))/2)^n+((1-sqrt(5))/2)^n) 假设F[n]可以表示成 t * 10^k(t是一个小数),那么对于F[n]取对数log10,答案就为log10 t + K,此时很明显log10 t<

hdu 2604 递推 矩阵快速幂

HDU 2604 Queuing (递推+矩阵快速幂) 这位作者讲的不错,可以看看他的 #include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <cstring> using namespace std; const int N = 5; int msize, Mod; struct Mat { int mat[N][N]; }; M