根据一些数学知识可以知道形如fn=pfn−1+qfn−2fn=pfn−1+qfn−2的数列,设方程x2−px−q=0x2−px−q=0存在两实数根为x1,x2x1,x2,则fnfn可以被表示为fn=Axn1+Bxn2fn=Ax1n+Bx2n的形式,且通过f0,f1f0,f1可以求出AA和。在本题中取x1=b+d√2,x2=b−d√2,A=B=1x1=b+d2,x2=b−d2,A=B=1,可以求出上文中的p,q,f0,f1p,q,f0,f1。通过题目限制可以发现四者都是整数,因此fnfn也是整数。
然后用矩阵乘法做递推即可。最后答案等于fn−xn2fn−x2n,注意到|x2|<1|x2|<1,所以最多只有1的误差,特判即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define mod 7528443412579576937ll
#define lint long long
#define ull unsigned long long
using namespace std;
inline lint pls(lint a,lint b) { return (lint)(((ull)a+b)%mod); }
inline lint tms(lint a,lint b,lint ans=0)
{ for(;b;b>>=1,a=pls(a,a)) (b&1ll)?ans=pls(ans,a):0;return ans; }
struct node{
lint a,b,c,d;
node(lint _a=1,lint _b=0,lint _c=0,lint _d=1)
{ a=_a,b=_b,c=_c,d=_d; }
inline node operator=(const node &n)
{ return a=n.a,b=n.b,c=n.c,d=n.d,*this; }
inline node operator*(const node &n)const
{
node r;
r.a=pls(tms(a,n.a),tms(b,n.c)),
r.b=pls(tms(a,n.b),tms(b,n.d)),
r.c=pls(tms(c,n.a),tms(d,n.c)),
r.d=pls(tms(c,n.b),tms(d,n.d));
return r;
}
inline node operator*=(const node &n)
{ return (*this)=(*this)*n; }
};
inline node fast_pow(node x,lint k,node ans=node())
{ for(;k;k>>=1,x*=x) (k&1ll)?ans*=x,0:0;return ans; }
int main()
{
lint b,d,n;scanf("%lld%lld%lld",&b,&d,&n);
node t=fast_pow(node(b,(d-b*b)/4%mod,1,0),n);
lint ans=pls(tms(t.c,b),tms(t.d,2));
if(n%2==0&&d!=b*b) ans=(lint)((ans-1ull+mod)%mod);
return !printf("%lld\n",ans);
}