HDU 6172 Array Challenge (打表找規律+矩陣快速冪 17多校第十場第2題)
阿新 • • 發佈:2019-01-01
題目連結
題意
分析
不得不佩服AC這道題的人腦洞,為什麼你們這麼熟練。。。打表找規律無所不能。
因為我們無法處理開方的取模問題,因此我們不能一步步求。我們令
發現
由於轉移矩陣出現了負數,取模的時候要注意!
程式碼
#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;
}