BZOJ 4002: [JLOI2015]有意义的字符串
作者:互联网
看到式子的形式,可以想到斐波那契数列的通项的形式
设 \(f_n = \left(\dfrac{b+\sqrt d}{2}\right)^n + \left(\dfrac{b-\sqrt d}{2}\right)^n\)
这两个是方程 \(x^2-bx+\dfrac{b^2-d}{4}=0\) 的两根
根据特征方程及特征根可以得到递推式 \[f_n=bf_{n-1}-\frac{b^2-d}{4}f_{n-2}\]
两个系数都是整数,那么可以矩阵快速幂得到 \(f_n\) 的值
而 \(\text{ans}=f_n - \left(\dfrac{b-\sqrt d}{2}\right)^n\)
当 \(n\) 为奇数时,下取整右半部分为 \(0\)
当 \(n\) 为偶数时,下取整右半部分为 \(-1\)
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) >> 1)
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define Edg int ccnt=1,head[N],to[N*2],ne[N*2];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[N*2],ne[N*2],c[N*2];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const ll MOD = 7528443412579576937ll;
void M(ll &x) {if (x >= MOD)x -= MOD; if (x < 0)x += MOD;}
int qp(int a, int b = MOD - 2) {int ans = 1; for (; b; a = 1LL * a * a % MOD, b >>= 1)if (b & 1)ans = 1LL * ans * a % MOD; return ans % MOD;}
int gcd(int a, int b) { while (b) { a %= b; std::swap(a, b); } return a; }
ll add(ll x, ll y) {
ull z = ull(x) + ull(y);
return z >= MOD ? z - MOD : z;
}
ll mul(ll a, ll b) {
ll ans = 0;
while (b) {
if (b & 1) ans = add(ans, a);
a = add(a, a);
b >>= 1;
}
return ans;
}
struct Mat {
ll mat[2][2];
Mat() { memset(mat, 0, sizeof(mat)); }
Mat operator * (const Mat &p) const {
Mat c;
rep (i, 0, 2)
rep (j, 0, 2)
rep (k, 0, 2)
c.mat[i][j] = add(c.mat[i][j], mul(mat[i][k], p.mat[k][j]));
return c;
}
};
Mat qp(Mat a, ll b) {
Mat res;
res.mat[0][0] = res.mat[1][1] = 1;
while (b) {
if (b & 1) res = res * a;
a = a * a;
b >>= 1;
}
return res;
}
int main() {
ll b, d, n;
scanf("%lld%lld%lld", &b, &d, &n);
if (n == 0) {
puts("1");
return 0;
}
Mat res;
res.mat[0][0] = b; res.mat[0][1] = MOD - ((b * b - d) >> 2);
res.mat[1][0] = 1;
res = qp(res, n - 1);
ll ans = add(mul(res.mat[0][0], b), mul(res.mat[0][1], 2));
if (n % 2 == 0) ans--;
if (ans < 0) ans += MOD;
printf("%lld\n", ans);
return 0;
}
标签:JLOI2015,mat,int,res,4002,ans,MOD,ll,BZOJ 来源: https://www.cnblogs.com/Mrzdtz220/p/12358719.html