hdu 4686 (矩阵快速幂)

题意:

0 = A0 
         a i = a i-1*AX+AY 
         b 0 = B0 
         b i = b i-1*BX+BY

求AoD(N) mod 1000000007

思路:

做这道题时思路没有打开,一直纠结于如何把公式加一起.....

正确是做法是把AoD这个和加到你的构造矩阵里来递推计算

aibi=(Ax*Bx)*ai-1*bi-1 + (Ax*By)*ai-1 + (Ay*Bx)*bi-1 + Ay*By

代码:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

typedef long long ll;
const int N=5,M=5,P=5;
const ll MOD=1000000007;
struct  Matrix
{
    ll m[N][N];
};

Matrix  A;

Matrix  I={1,0,0,0,0,
           0,1,0,0,0,
           0,0,1,0,0,
           0,0,0,1,0,
           0,0,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>>=1;
      p=multi(p,p);
    }
    return ans;
}

int main(int argc, char const *argv[])
{
    ll n;
    ll A0,Ax,Ay,B0,Bx,By;
    while(cin>>n)
    {
        scanf("%lld %lld %lld",&A0,&Ax,&Ay);
        scanf("%lld %lld %lld",&B0,&Bx,&By);
        if(n==0)
        {
            cout<<"0"<<endl;
            continue;
        }
        A0%=MOD;
        Ax%=MOD;
        Ay%=MOD;
        B0%=MOD;
        Bx%=MOD;
        By%=MOD;
        A.m[0][0]=1;
        A.m[0][1]=(Ax*Bx)%MOD;
        A.m[0][2]=(Ax*By)%MOD;
        A.m[0][3]=(Ay*Bx)%MOD;
        A.m[0][4]=(Ay*By)%MOD;
        A.m[1][0]=0;
        A.m[1][1]=(Ax*Bx)%MOD;
        A.m[1][2]=(Ax*By)%MOD;
        A.m[1][3]=(Ay*Bx)%MOD;
        A.m[1][4]=(Ay*By)%MOD;
        A.m[2][0]=0;
        A.m[2][1]=0;
        A.m[2][2]=(Ax)%MOD;
        A.m[2][3]=0;
        A.m[2][4]=(Ay)%MOD;
        A.m[3][0]=0;
        A.m[3][1]=0;
        A.m[3][2]=0;
        A.m[3][3]=(Bx)%MOD;
        A.m[3][4]=(By)%MOD;
        A.m[4][0]=0;
        A.m[4][1]=0;
        A.m[4][2]=0;
        A.m[4][3]=0;
        A.m[4][4]=1;
        Matrix ans=power(A,(n-1));
        ll num=0;
        ll a=(A0*B0)%MOD;
        ll b=(A0*B0)%MOD;
        ll c=A0%MOD;
        ll d=B0%MOD;
        ll e=1;
        num=(num+(ans.m[0][0]*a)%MOD)%MOD;
        num=(num+(ans.m[0][1]*b)%MOD)%MOD;
        num=(num+(ans.m[0][2]*c)%MOD)%MOD;
        num=(num+(ans.m[0][3]*d)%MOD)%MOD;
        num=(num+(ans.m[0][4]*e)%MOD)%MOD;
        printf("%lld\n",num);
    }
    return 0;
}
时间: 2024-08-02 09:05:10

hdu 4686 (矩阵快速幂)的相关文章

HDU 4965 矩阵快速幂

顺手写了下矩阵类模板 利用到矩阵乘法的交换律 (A*B)^n == A * (B*A)^n-1 *B #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #include <utility> #include <stack> #includ

hdu 4965 矩阵快速幂 矩阵相乘性质

Fast Matrix Calculation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 170    Accepted Submission(s): 99 Problem Description One day, Alice and Bob felt bored again, Bob knows Alice is a gir

HDU 5895 矩阵快速幂+高次幂取模

HDU 5895 Mathematician QSC 题意:已知f(n)=2*f(n-1)+f(n-2), g(n)=∑f(i)²(0<=i<=n), 给出n,x,y,s, 求x^(g(n*y))%(s+1); 思路:OEIS查到了g(n)=f(n)*f(n+1)/2, f(n)可以用矩阵快速幂求得, 有一个定理可以用于高次幂取模 x^n %k=x^(n%phi(k)+phi(k)) %k, 此处phi(x)为欧拉函数,但是在对幂次取模时存在一个除2, 又因为(a/b)%k=(a%bk)/b,

hdu 1757 (矩阵快速幂) 一个简单的问题 一个简单的开始

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1757 题意不难理解,当x小于10的时候,数列f(x)=x,当x大于等于10的时候f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10); 所求的是f(x)取m的模,而x,m,a[0]至a[9]都是输入项 初拿到这道题,最开始想的一般是暴力枚举,通过for循环求出f(x)然后再取模,但是有两个问题,首先f(x)可能特别大,其

HDU 2855 (矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2855 题目大意:求$S(n)=\sum_{k=0}^{n}C_{n}^{k}Fibonacci(k)$ 解题思路: 题目挺吓人的.先把完整组合数+Fibonacci展开来. 利用Fibonacci的特性,从第一项开始消啊消,消到只有一个数: $S(0)=f(0)$ $S(1)=f(2)$ $S(2)=f(4)$ $S(n)=f(2*n)$ 这样矩阵快速幂就可以了,特判$n=0$时的情况. 快速幂矩阵

hdu 4549 (矩阵快速幂+费马小定理)

题意:已知F0=a,F1=b,Fn=Fn-1*Fn-2,给你a,b,n求Fn%1000000007的值 思路:我们试着写几组数 F0=a F1=b F2=a*b F3=a*b2 F4=a2*b3 F5=a3*b5 我们发现a,b的系数其实是斐波那契数列,我们只需用矩阵快速幂求出相应系数就行,但是 这个系数随着增长会特别大,这时我们需要利用费马小定理进行降幂处理 费马小定理 ap-1≡1(mod p) 代码: #include <iostream> #include <cmath>

HDU 3221 矩阵快速幂+欧拉函数+降幂公式降幂

装载自:http://www.cnblogs.com/183zyz/archive/2012/05/11/2495401.html 题目让求一个函数调用了多少次.公式比较好推.f[n] = f[n-1]*f[n-2].然后a和b系数都是呈斐波那契规律增长的.需要先保存下来指数.但是太大了.在这里不能用小费马定理.要用降幂公式取模.(A^x)%C=A^(x%phi(C)+phi(C))%C(x>=phi(C)) Phi[C]表示不大于C的数中与C互质的数的个数,可以用欧拉函数来求. 矩阵快速幂也不

hdu 2842(矩阵快速幂+递推)

题意:一个中国环的游戏,规则是一个木棒上有n个环,第一个环是可以随意放上或拆下的,剩下的环x如果想放上或拆下必须前一个环x-1是放上的且前x-2个环全部是拆下的,问n个环最少多少次操作可以全部拆掉. 题解:需要进行递推,首先第一步肯定是要拆第n个环保证操作次数最少,因为后面的环是否存在对前面的环不造成影响,而先拆前面的如果要拆后面的环还是要把前面的放上,f(n)表示拆掉前n个环需要的最少操作次数,先拆第n个要拆前n-2个再拆第n个,花费f(n-2)+1,然后这时是00-0010,要拆第n-1个需

hdu 4291(矩阵快速幂 + 循环节)

题意:求s s = g(g(g(n))) mod 1000000007 其中g(n) g(n) = 3g(n - 1) + g(n - 2) g(1) = 1 g(0) = 0 题解:普通的矩阵快速幂会超时,看到别人的题解是需要计算循环节得到小的MOD从而减小计算量.1000000007太大,需要计算更小的一个循环节,新技能get. #include <stdio.h> #include <string.h> struct Mat { long long g[3][3]; }ori