1. 程式人生 > >HDU 6172 Array Challenge (打表找規律+矩陣快速冪 17多校第十場第2題)

HDU 6172 Array Challenge (打表找規律+矩陣快速冪 17多校第十場第2題)

題目連結

題意

這裡寫圖片描述

分析

不得不佩服AC這道題的人腦洞,為什麼你們這麼熟練。。。打表找規律無所不能。
因為我們無法處理開方的取模問題,因此我們不能一步步求。我們令fn=an,則打表看fn的前幾項,f2=31 ,f3=197 ,f4=1255
發現fn符合類似於hn的遞推式,fn=4fn1+17fn212fn3,是個三階線性遞推式,用矩陣快速冪解決即可。

fnfn1fn2=41017011200n4f4f3f2
由於轉移矩陣出現了負數,取模的時候要注意!

程式碼

#include <iostream>
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <string> #define ls (rt<<1) #define rs (rt<<1|1) #define bit(x) (1<<(x)) using namespace std; typedef long long LL; const double pi=4*atan(1.0); const
int INF=0x3f3f3f3f; const double eps=1e-6; const int MAXN=5; const int MOD=1000000007; struct Mat { LL mat[MAXN+1][MAXN+1]; }p,q,x; Mat operator *(Mat a,Mat b) { Mat c; memset(c.mat,0,sizeof(c.mat)); for (int k=1;k<=MAXN;k++) { for (int i=1;i<=MAXN;i++) { if
(a.mat[i][k]==0) continue; for (int j=1;j<=MAXN;j++) { if (b.mat[k][j]==0) continue; c.mat[i][j]+=(((a.mat[i][k]*b.mat[k][j])%MOD+MOD)%MOD);///防止出現負數 c.mat[i][j]%=MOD; } } } return c; } Mat operator ^(Mat a,LL k) { Mat c; int i,j; for (i=1;i<=MAXN;i++) for (j=1;j<=MAXN;j++) c.mat[i][j]=(i==j); for (;k;k>>=1) { if (k&1) c=c*a; a=a*a; } return c; } void Init() { p.mat[1][1]=4;p.mat[1][2]=17;p.mat[1][3]=(-12); p.mat[2][1]=1;p.mat[2][2]=0;p.mat[2][3]=0; p.mat[3][1]=0;p.mat[3][2]=1;p.mat[3][3]=0; q.mat[1][1]=1255;q.mat[2][1]=197;q.mat[3][1]=31; } int main() { int T; LL n; //freopen("in.txt","r",stdin); Init(); scanf("%d",&T); while (T--) { scanf("%lld",&n); if (n==2) printf("31\n"); else if (n==3) printf("197\n"); else { x=(p^(n-4))*q; printf("%lld\n",x.mat[1][1]); } } return 0; }