一阶常系数线性递推式的特征方程
显然是等差数列,我们考虑
参数法:设
有
那么
设
容易解出等比数列
的通项
就可以推出
的通项
二阶常系数线性递推式的特征方程
仍然考虑类比参数法 可以通过一大堆复杂的推导变换得到。。。。
至于一般的常系数线性递推式也可以用生成函数分类讨论搞搞
结论:对
移项
导出
则
则
利用已知的两个
可以解出
和
得到通项
特征根法
因为某考的原因 搞出了这样的结论来背:
仅对于
其中
导出
其根称为特征根
设
设
可以说是很牛逼了;怎么用呢?
先解特征根,设出
求
和
的关系
然后就可以求
通项
本题
模数太丑了,设它为
我们现在是要求
发现
都很大,考虑展开?
还是搞不了
这个下取整也并没有留给我们什么好的性质,只能考虑究竟能不能快速计算那个幂
我们发现这东西好像半个斐波那契
那我们考虑
然后就可以随便做一下了 不难得到
分类讨论后面那项即可。特判
注意这个很丑的模数
它非常接近 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;
}