其他分享
首页 > 其他分享> > BZOJ 4002: [JLOI2015]有意义的字符串

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