• 校内训练0602 习题exercise


    【题目大意】

    f(i)=((Af(i-1)+B)/(Cf(i-1)+D)) mod P。

    给出f(0), A, B, C, D, P, n,求f(n)。

    多组数据T<=1e4

    n<=1e18, P <= 1e9, |f(0)|,|A|,|B|,|C|,|D| <= 1e9

    保证任何时候存在逆元。

    【题解】

    首先我们有一种O(TP)的做法:找循环节。

    考场上因为数据原因是可以AC的。。

    # include <map>
    # include <stdio.h>
    # include <assert.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10;
    
    # define RG register
    # define ST static
    
    int A, B, C, D, mod, lm, rm;
    ll f[2000010], n;
    map<int, int> mp;
    
    inline ll exgcd(ll a, ll b, ll &x, ll &y) {
        if(b == 0) {
            x = 1;
            y = 0;
            return a;
        }
        exgcd(b, a%b, x, y);
        ll t = x;
        x = y;
        y = t - (a/b)*y;
    }
    
    inline ll getinv(ll n) {
        ll x, y;
        exgcd(n, (ll)mod, x, y);
        x = (x%mod + mod) % mod;
        return x;
    }
    
    inline void sol() {
        scanf("%lld%d%d%d%d%lld%d", &f[0], &A, &B, &C, &D, &n, &mod);
        A = (A+mod)%mod; B = (B+mod)%mod;
        C = (C+mod)%mod; D = (D+mod)%mod;
        mp.clear(); lm = rm = -1; mp[f[0]] = 0;
        for (int i=1; i<=mod; ++i) {
            f[i] = (A*f[i-1] + B) % mod * getinv(C*f[i-1] + D) % mod;
            if(mp.find(f[i]) != mp.end()) {
                lm = mp[f[i]], rm = i;
                break;
            }
            mp[f[i]] = i;
        }
    //    printf("%d %d
    ", lm, rm);
        assert(lm != -1 && rm != -1);
        if(n <= lm) printf("%lld
    ", f[n]);
        else printf("%lld
    ", f[(n-lm)%(rm-lm)+lm]);
    }
    
    int main() {
        freopen("exercise.in", "r", stdin);
        freopen("exercise.out", "w", stdout);
        int T; cin >> T;
        while(T--) sol(); 
        return 0;
    }
    View Code

    标准做法是

    f(i)=((Af(i-1)+B)/(Cf(i-1)+D))

    f(i-1)=((Af(i-2)+B)/(Cf(i-2)+D))

    那么

    f(i)=((A^2+BC)f(i-2)+(AB+BD))//((AC+CD)f(i-2)+(CD+D^2))

    相当于两个2*2的矩阵乘在一起。

    那么矩乘即可。

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10;
    
    # define RG register
    # define ST static
    
    int f0, A, B, C, D, mod, ans;
    ll n;
    
    inline ll exgcd(ll a, ll b, ll &x, ll &y) {
        if(b == 0) {
            x = 1;
            y = 0;
            return a;
        }
        exgcd(b, a%b, x, y);
        ll t = x;
        x = y;
        y = t - (a/b)*y;
    }
    
    inline int getinv(ll n) {
        ll x, y;
        exgcd(n, (ll)mod, x, y);
        x = (x%mod + mod) % mod;
        return x;
    }
    
    struct matrix {
        int a[3][3], n;
        inline void set() {memset(a, 0, sizeof a);}
        friend matrix operator * (matrix a, matrix b) {
            matrix c; c.set();
            for (int i=1; i<=2; ++i)
                for (int j=1; j<=2; ++j)
                    for (int k=1; k<=2; ++k)
                        (c.a[i][j] += 1ll * a.a[i][k] * b.a[k][j] % mod) %= mod;
            return c;
        }
        friend matrix operator ^ (matrix a, ll b) {
            matrix c; c.set(); c.a[1][1] = c.a[2][2] = 1;
            while(b) {
                if(b&1) c=c*a;
                a=a*a;
                b >>= 1;
            }
            return c;
        }
    }E;
    
    inline void sol() {
        scanf("%d%d%d%d%d%lld%d", &f0, &A, &B, &C, &D, &n, &mod);
        A = (A+mod) % mod; B = (B+mod) % mod; C = (C+mod) % mod; D = (D+mod) % mod;
        E.set(); E.a[1][1] = A, E.a[1][2] = B, E.a[2][1] = C, E.a[2][2] = D;
        E = E^n;
        A = E.a[1][1], B = E.a[1][2], C = E.a[2][1], D = E.a[2][2];
        ans = getinv((ll)C * f0 + D);
        ans = 1ll * ans * (1ll * A * f0 % mod + B) % mod;
        printf("%d
    ", ans);
    }
    
    int main() {
        freopen("exercise.in", "r", stdin);
        freopen("exercise.out", "w", stdout);
        int T; cin >> T;
        while(T--) sol();
        return 0;
    }
    View Code
  • 相关阅读:
    POJ3889Fractal Streets
    POJ3263 Tallest Cow
    tyvjP1288 飘飘乎居士取能量块
    洛谷P3369 【模板】普通平衡树(Treap/SBT)
    洛谷P1063 能量项链 [2006NOIP提高组]
    洛谷P1541 乌龟棋 [2010NOIP提高组]
    POJ3322 Bloxorz I
    BZOJ1218:[HNOI2003]激光炸弹
    TyvjP1266 费解的开关
    洛谷P3070 [USACO13JAN]岛游记Island Travels
  • 原文地址:https://www.cnblogs.com/galaxies/p/20170602_a.html
Copyright © 2020-2023  润新知