Starry的神奇魔法 矩阵快速幂

题目描述

       啦啦啦,Starry正愉快的做着编程题,代码是多么优美呀!突然,有人问他一道数学题,对于数学渣渣的Starry来说,这是多么的烦恼呀。不过不要紧,他还可以问其他人的,所以他想到了聪明的你们。这个问题是由一个神奇的魔法师提出的,他创造了一种魔法,每次使用魔法可以让今天的魔力值为前一天魔力值的2018倍+前两天魔力值的8倍+前三天魔力值的12倍。当然,一天只能使用一次魔法,除了使用魔法外,每天魔法师还能产生8888的魔力值。第一、二、三天的初始魔力值为888。他想问的是第n天他可以拥有多少魔力值。

输入

第一行输入一个T表示有TT个问题(1T104)(1≤T≤104)。

接下来T行,每行有一个数n1n1018n(1≤n≤1018),表示第nn天。

输出

输出TT行,每行输出第nn天的魔力值,由于数很大,结果对2018081220180812取模。

样例输入

3
2
5
8

样例输出

888
17299052
16854116

解题思路:数据太大,不能打表不能暴力,就用矩阵快速幂。
矩阵1:{888,888,888,8888},矩阵二:{{2018,1,0,0},{8,0,1,0},{12,0,0,0},{1,0,0,1}};
矩阵1的意义:{f1,f2,f3,c},fn为第几的天数,c为常量。推导见基础矩阵快速幂的斐波那契数列;参考博客:https://www.cnblogs.com/cmmdc/p/6936196.html
以下为ac代码:
 1 #include<iostream>
 2 using namespace std;
 3 const int mod=20180812;
 4 struct P{
 5     long long a[4][4];
 6 }num,rex;
 7 long long f[4];
 8 void init()
 9 {
10     f[0]=f[1]=f[2]=888;f[3]=8888;
11     num.a[0][0]=2018;num.a[0][1]=1;num.a[0][2]=0;num.a[0][3]=0;
12     num.a[1][0]=8;num.a[1][1]=0;num.a[1][2]=1;num.a[1][3]=0;
13     num.a[2][0]=12;num.a[2][1]=0;num.a[2][2]=0;num.a[2][3]=0;
14     num.a[3][0]=1;num.a[3][1]=0;num.a[3][2]=0;num.a[3][3]=1;
15     return;
16 }
17 P fun(P x,P y)
18 {
19     P tmp;
20     for(int i=0;i<4;i++)
21     for(int j=0;j<4;j++)
22         tmp.a[i][j]=0;
23     for(int i=0;i<4;i++)
24     for(int j=0;j<4;j++)
25     for(int k=0;k<4;k++)
26         tmp.a[i][j]=(tmp.a[i][j]+(x.a[i][k]*y.a[k][j])%mod)%mod;
27     return tmp;
28 }
29 void quickp(long long n)
30 {
31     for(int i=0;i<4;i++)
32     for(int j=0;j<4;j++)
33     {
34         if(i==j) rex.a[i][j]=1;
35         else rex.a[i][j]=0;
36     }
37     while(n)
38     {
39         if(n&1)
40             rex=fun(rex,num);
41         num=fun(num,num);
42         n>>=1;
43     }
44     return;
45 }
46 int main()
47 {
48     long long t,n;
49     scanf("%lld",&t);
50     while(t--)
51     {
52         long long ans=0;
53         init();
54         scanf("%lld",&n);
55         if(n<=3)
56         cout<<"888"<<endl;
57         else
58         {
59             quickp(n-3);
60             for(int i=0;i<4;i++)
61                 ans=(ans+(f[i]*rex.a[i][0])%mod)%mod;
62             printf("%lld\n",ans);
63         }
64     }
65     return 0;
66 }

 

posted @ 2018-08-13 13:27  超人不穿内裤  阅读(214)  评论(0编辑  收藏  举报