思路:
一开始比赛的时候学长忘记将取模数加上去了,人均放弃打高精。
距离比赛结束还有半个小时,学长才想起来加上模数,
直接光速切题。
此题我们考虑用地推来做。
设f[i][0/1/2]现在到第i位,已经前面(紧连着)连续出现了0/1/2个A的答案。
- f[i][0] = f[i-1][1]+f[i-1][0]+f[i-1][2]
- f[i][1] = f[i-1][0]
- f[i][2] = f[i-1][1]
我们稍微对柿子错一下位置,则 f[i][0]=>f[i-1][0] , f[i][1]=f[i-1][1]
那递推式就变成了
f[i]=f[i−1]+f[i−2]+f[i−3]f[i] = f[i-1]+f[i-2]+f[i-3]f[i]=f[i−1]+f[i−2]+f[i−3]
对于100pts的数据,我们发现有点小大,
考虑用矩阵快速幂优化递推。
构造一个单位矩阵为:
{ 0 0 1 1 0 1 1 1 1}\left\{\begin{array}{lcc}\;\;0&\;\;0\;\;\;\;\;1&{}\\\;\;1&\;\;0\;\;\;\;\;1&{}\\\;\;1&\;\;1\;\;\;\;\;1&\end{array}\right\}⎩⎨⎧011010111⎭⎬⎫
构造一个1*3的答案矩阵:
{fi−2fi−1fi}\{\begin{array}{ccc}f_{i-2}&f_{i-1}&f_i\end{array}\}{fi−2fi−1fi}
将单位矩阵n-3次方的得数再乘上答案矩阵就是答案。
Ps: 注意一下在矩阵乘法中的取模运算!!!
#include <cstdio>
#include <iostream>
#include <cstring>
#define mod 19260817
#define ll long long
using namespace std;
const int N = 10;
struct Maxtrix
{
ll line, row, m[N][N];
Maxtrix(ll x, ll y)
{
line = x, row = y;
memset(m, 0, sizeof(m));
}
} ans(3,3), res(3,3), c(3,3), a(3,3), s(3,3);
ll T, n, f[N];
inline ll read()
{
ll x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9')
{
if(c == '-') f = -f;
c = getchar();
}
while(c >= '0' && c <= '9')
{
x = x * 10 + (c - '0');
c = getchar();
}
return x * f;
}
inline void write(ll x)
{
if(x < 10) {putchar(x + 48); return ;}
write(x / 10);
putchar(x % 10 + 48);
}
void csh()
{
ans.line = 1, ans.row = 3;
res.line = res.row = 3;
ans.m[1][1] = 2, ans.m[1][2] = 4, ans.m[1][3] = 7;
res.m[2][1] = res.m[3][2] = res.m[1][3] = res.m[2][3] = res.m[3][3] = 1;
}
Maxtrix mul(Maxtrix A, Maxtrix B)
{
Maxtrix tmp(A.line,B.row);
for(ll i = 1; i <= tmp.line; i++)
for(ll j = 1; j <= tmp.row; j++)
for(ll k = 1; k <= A.row; k++)
tmp.m[i][j] = (tmp.m[i][j] + A.m[i][k] * B.m[k][j] % mod) % mod;
return tmp;
}
Maxtrix ksm(Maxtrix a, ll k)
{
Maxtrix c(a.line, a.row);
for(int i = 1; i <= 3; i++) c.m[i][i] = 1; //乘法要从一开始作文章
while(k)
{
if(k & 1) c = mul(c, a);
a = mul(a, a);
k >>= 1;
}
return c;
}
int main()
{
T = read();
csh();
f[1]=2,f[2]=4,f[3]=7;
while(T--)
{
n = read();
if(n<=3)
{
cout<<f[n]<<endl;
continue ;
}
c = mul (ans, ksm(res, n - 3));
printf("%lld\n", c.m[1][3]);
}
return 0;
}