Count HDU-6470 构造矩阵、矩阵快速幂

Count

Problem Description

Farmer John有n头奶牛.
某天奶牛想要数一数有多少头奶牛,以一种特殊的方式:
第一头奶牛为1号,第二头奶牛为2号,第三头奶牛之后,假如当前奶牛是第n头,那么他的编号就是2倍的第n-2头奶牛的编号加上第n-1头奶牛的编号再加上自己当前的n的三次方为自己的编号.
现在Farmer John想知道,第n头奶牛的编号是多少,估计答案会很大,你只要输出答案对于123456789取模.

Input

第一行输入一个T,表示有T组样例
接下来T行,每行有一个正整数n,表示有n头奶牛 (n>=3)
其中,T=10^4,n<=10^18

Output

共T行,每行一个正整数表示所求的答案

 

Sample Input

5

3

6

9

12

15

Sample Output

31

700

7486

64651

527023

 

矩阵快速幂的模板题,题目已经给出公式An=An-1+2(An-1)+n*n*n ,然后构造这道题的矩阵就可以了

因为这个道题的矩阵的维数有些多,构造可能没有那么简单所以我们先过一遍斐波那契的矩阵

An=An-1+An-2

 \begin{bmatrix} An \\ An-1 \end{bmatrix} = \begin{bmatrix}An-1 \\ An-2 \end{bmatrix} * \begin{bmatrix} 1 & 1\\ 1& 0 \end{bmatrix} = \begin{bmatrix} An-1+An-2\\ An-1 \end{bmatrix} = \begin{bmatrix} An\\ An-1 \end{bmatrix}

所以斐波那契构造的矩阵为\begin{bmatrix} 1 & 1\\ 1 & 0 \end{bmatrix}

然后这道题目也是一样,主要需要构成n*n*n

n^{_{3}}=(n-1)^{^{3}}+3(n-1)^{2}+3(n-1)+1

n^{^{2}}=(n-1)^{^{2}}+2(n-1)+1

n=(n-1)+1

通过以上构造的矩阵为:(矩阵可能不同,最后算答案的时候计算公式也不同)

\begin{bmatrix} 1 &2& 1& 3& 3 & 1\\ 1& 0& 0& 0 &0 &0 \\ 0& 0 & 1 & 3& 3& 1\\ 0& 0 & 0 & 1& 2 &1 \\ 0&0 &0 & 0 &1 & 1\\ 0& 0 & 0 & 0 & 0 & 1 \end{bmatrix}

第一部分           第二部分                第三部分

\begin{bmatrix} An\\ An-1\\ n^{3}\\ n^{^{2}}\\ n\\ 1 \end{bmatrix} = \begin{bmatrix} An-1\\ An-2\\ (n-1)^{3}\\ (n-1)^{2}\\ (n-1)\\ 1 \end{bmatrix} * \begin{bmatrix} 1 &2 &1 & 3& 3&1 \\ 1& 0 & 0& 0&0 &0 \\ 0& 0&1 & 3& 3 &1 \\ 0 &0 & 0 &1 & 2& 1\\ 0 & 0& 0& 0 & 1&1 \\ 0&0 & 0 & 0 &0 & 1 \end{bmatrix}

矩阵就给出来了,然后直接上代码

#include<bits/stdc++.h>
using namespace std;
struct node{
    long long m[6][6];
}res,A;
const int M=123456789;
node mul(node x,node y)
{
    node v;
    memset(v.m,0,sizeof(v.m)); 
    for(int i=0;i<6;i++)
        for(int j=0;j<6;j++)
            for(int k=0;k<6;k++)
            {
                v.m[i][j]+=x.m[i][k]*y.m[k][j];
                v.m[i][j]=(v.m[i][j]+M)%M;//一定要记得先加M 
            }
            return v;
}
node ful(node x,long long n)//快速幂内容 
{
    memset(res.m,0,sizeof res.m);
    for(int i=0;i<6;i++) res.m[i][i]=1;
    while(n)
    {
        if(n&1) res=mul(res,x);
        x=mul(x,x);
        n>>=1;
    }
    return res;
}
int main()
{
    A={     1,2,1,3,3,1,
            1,0,0,0,0,0,
            0,0,1,3,3,1,
            0,0,0,1,2,1,
            0,0,0,0,1,1,
            0,0,0,0,0,1
    };
    int t;
    scanf("%d",&t);
    while(t--)
    {
        long long n;
        scanf("%lld",&n);
        if(n<3) printf("%lld\n",n);
        else{
            node v=ful(A,n-2);
            long long ccc=v.m[0][0]*2+v.m[0][1]*1+v.m[0][2]*8+v.m[0][3]*4+v.m[0][4]*2+v.m[0][5];
            //矩阵从n=3开始,然后带入第二部分的值,例如A3-1=2,A2-1=1,(3-1)^3=8,(3-1)^2=4 
            ccc%=M;
            printf("%lld\n",ccc);
        }    
    }
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值