一阶常系数线性递推式的特征方程
a
n
+
1
=
k
a
n
+
d
a_{n+1}=ka_n+d
an+1=kan+d
k
=
1
k=1
k=1 显然是等差数列,我们考虑
k
≠
1
k\ne1
k̸=1
参数法:设
a
n
+
1
+
t
=
k
(
a
n
+
t
)
a_{n+1}+t=k(a_n+t)
an+1+t=k(an+t)
有
a
n
+
1
=
k
a
n
+
(
k
−
1
)
t
a_{n+1}=ka_n+(k-1)t
an+1=kan+(k−1)t
那么
(
k
−
1
)
t
=
d
(k-1)t=d
(k−1)t=d
a
n
+
1
+
d
k
−
1
=
k
(
a
n
+
d
k
−
1
)
a_{n+1}+\frac{d}{k-1}=k(a_n+\frac{d}{k-1})
an+1+k−1d=k(an+k−1d)
设
b
n
=
a
n
+
d
k
−
1
b_n=a_{n}+\frac{d}{k-1}
bn=an+k−1d
容易解出等比数列
b
n
b_n
bn 的通项
就可以推出
a
n
a_n
an 的通项
二阶常系数线性递推式的特征方程
仍然考虑类比参数法 可以通过一大堆复杂的推导变换得到。。。。
至于一般的常系数线性递推式也可以用生成函数分类讨论搞搞
结论:对
f
(
n
)
=
c
1
f
(
n
−
1
)
+
c
2
f
(
n
−
2
)
f(n)=c_1f(n-1)+c_2f(n-2)
f(n)=c1f(n−1)+c2f(n−2)
移项
f
(
n
)
−
c
1
f
(
n
−
1
)
−
c
2
f
(
n
−
2
)
=
0
f(n)-c_1f(n-1)-c_2f(n-2)=0
f(n)−c1f(n−1)−c2f(n−2)=0
导出
x
2
−
c
1
x
−
c
2
=
0
x^2-c_1x-c_2=0
x2−c1x−c2=0
Δ
≠
0
\Delta\ne0
Δ̸=0 则
f
(
n
)
=
A
x
1
n
+
B
x
2
n
f(n)=Ax_1^n+Bx_2^n
f(n)=Ax1n+Bx2n
Δ
=
0
\Delta=0
Δ=0 则
f
(
n
)
=
(
A
+
B
n
)
x
n
f(n)=(A+Bn)x^n
f(n)=(A+Bn)xn
利用已知的两个
f
f
f 可以解出
A
A
A 和
B
B
B 得到通项
特征根法
因为某考的原因 搞出了这样的结论来背:
仅对于
A
a
n
+
1
a
n
+
B
a
n
+
1
+
C
a
n
+
D
=
0
Aa_{n+1}a_n+Ba_{n+1}+Ca_n+D=0
Aan+1an+Ban+1+Can+D=0 其中
a
≠
0
a\ne0
a̸=0
导出
A
x
2
+
(
B
+
C
)
x
+
D
=
0
Ax^2+(B+C)x+D=0
Ax2+(B+C)x+D=0 其根称为特征根
Δ
≠
0
\Delta\ne0
Δ̸=0 设
b
n
=
a
n
−
x
1
a
n
−
x
2
b_n=\frac{a_n-x_1}{a_n-x_2}
bn=an−x2an−x1
Δ
=
0
\Delta=0
Δ=0 设
b
n
=
1
a
n
−
x
b_n=\frac{1}{a_n-x}
bn=an−x1
可以说是很牛逼了;怎么用呢?
先解特征根,设出
b
n
b_n
bn
求
b
n
+
1
b_{n+1}
bn+1 和
b
n
b_n
bn 的关系
然后就可以求
a
n
a_n
an 通项
本题
模数太丑了,设它为
p
p
p
我们现在是要求
⌊
(
b
+
d
2
)
n
⌋
(
m
o
d
p
)
\left\lfloor\left(\frac{b+\sqrt{d}}{2}\right)^n\right\rfloor\pmod p
⌊(2b+d)n⌋(modp)
发现
b
,
d
,
n
b,d,n
b,d,n 都很大,考虑展开?
⌊
∑
i
=
0
n
(
n
i
)
b
i
(
d
)
n
−
i
2
n
⌋
\left\lfloor\frac{\sum\limits_{i=0}^n{{n\choose i}b^i\left(\sqrt{d}\right)^{n-i}}}{2^n}\right\rfloor
⎣⎢⎢⎢2ni=0∑n(in)bi(d)n−i⎦⎥⎥⎥ 还是搞不了
这个下取整也并没有留给我们什么好的性质,只能考虑究竟能不能快速计算那个幂
我们发现这东西好像半个斐波那契
那我们考虑
f
(
n
)
=
(
b
+
d
2
)
n
+
(
b
−
d
2
)
n
f(n)=\left(\frac{b+\sqrt{d}}{2}\right)^n+\left(\frac{b-\sqrt{d}}{2}\right)^n
f(n)=(2b+d)n+(2b−d)n
f
(
n
)
=
b
f
(
n
−
1
)
+
d
−
b
2
4
f
(
n
−
2
)
f(n)=bf(n-1)+\frac{d-b^2}{4}f(n-2)
f(n)=bf(n−1)+4d−b2f(n−2)
f
(
0
)
=
2
,
f
(
1
)
=
b
f(0)=2,f(1)=b
f(0)=2,f(1)=b
然后就可以随便做一下了 不难得到
f
(
n
)
f(n)
f(n)
分类讨论后面那项即可。特判
n
=
0
n=0
n=0
注意这个很丑的模数
它非常接近 long long 的上限
所以我们得用 unsigned long long
每次运算还都要取模爽吗
不服去写高精
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cctype>
#include<ctime>
#include<algorithm>
using namespace std;
#define ll long long
#define cl const ll
cl p = 7528443412579576937ll;
ll b, d, n;
inline ll Add(cl& a, cl& b)
{
return (1ull*a + 1ull*b) % p;
}
inline ll Mul(ll a, ll b)
{
long long ret = 0;
while (b)
{
if (b & 1) ret = Add(ret, a);
a = Add(a, a);
b >>= 1;
}
return ret;
}
struct Matrix
{
ll x[2][2];
Matrix(cl&a=0,cl&b=0,cl&c=0,cl&d=0)
{
x[0][0] = a;
x[0][1] = b;
x[1][0] = c;
x[1][1] = d;
}
inline Matrix operator * (const Matrix& b)
{
Matrix Temp;
for (register int i = 0; i < 2; ++i)
{
for (register int j = 0; j < 2; ++j)
{
for (register int k = 0; k < 2; ++k)
{
Temp.x[i][j] = Add(Temp.x[i][j], Mul(x[i][k], b.x[k][j]));
}
}
}
return Temp;
}
inline void operator *= (const Matrix b)
{
*this = *this * b;
}
} matr;
inline Matrix qpow(Matrix x, ll k)
{
Matrix Ret(1,0,0,1);
while (k)
{
if (k & 1) Ret *= x;
x *= x;
k >>= 1;
}
return Ret;
}
Matrix trans;
int main()
{
scanf("%lld%lld%lld", &b, &d, &n);
if (n == 0) return putchar('1'), 0;
matr.x[0][0] = b; matr.x[1][0] = 2;
trans = Matrix(b, (d>>2)-Mul(b+1>>1,b-1>>1), 1, 0);
trans = qpow(trans,n-1) * matr;
if ((sqrt(1.0*b)!=1.0*d) && (!(n&1))) --trans.x[0][0];
if (trans.x[0][0]<0) trans.x[0][0]+=p;
printf("%lld", trans.x[0][0]);
return 0;
}