zoukankan      html  css  js  c++  java
  • 2021杭电多校1 HDU6956-Pass!【特征方程求解数列通向式+BSGS】

    题目链接
    赛中知道了(f(i)=(n-2)*f(i-1)+(n-1)*f(i-2)),然后考虑到矩阵上去了,然后歪了。
    思路
    看了题解才知道,可以将上式通过特征方程求解数列的通项公式求得
    (f(t)=frac{((n-1)^t+(n-1)*(-1)^t)}{n}=x (mod 998244353))
    写一下是如何推导出来的。
    已知(a_i=(n-2)*a_{i-1}+(n-1)*a_{i-2}),移项并构造一个类似等比数列的东西:
    (a_i-x*a_{i-1}=(a_{i-1}-x*a_{i-2})*y)
    那么可以发现
    (a_i=(x+y)*a_{i-1}-x*y*a_{i-2})
    (c_1=x+y,c_2=-x*y)其特征方程为:
    (x^2=c1*x+c2)(x^2=(n-2)*x+(n-1))
    求解可得 (x_1=-1,x_2=n-1)
    注意到原式子,代入(x1,x2)可通过
    (x+y=n-2,-x*y=n-1)
    求得(y1=n-1,y2=-1)

    由上文提到的这个式子 (a_i-x*a_{i-1}=(a_{i-1}-x*a_{i-2})*y) 通过移项得(frac{a_i-x*a_{i-1}}{a_{i-1}-x*a_{i-2}}=y),这是一个首项为(a_1-x*a_0),公比为(y)得等比数列,即:
    (a_i-x*a_{i-1}=(a_1-x*a_0)*y^{i-1})
    可列出方程组

    [ egin{cases} a_i-x_1*a_{i-1}=(a_1-x_1*a_0)*y_1^{i-1} \ a_i-x_2*a_{i-1}=(a_1-x_2*a_0)*y_2^{i-1} \ end{cases} ]


    (a_i=frac{(a_1-x_1*a_0)*y_1^{i-1}*x_2-(a_1-x_2*a_0)*y_2^{i-1}*x_1}{x_2-x_1})
    已知(a_0=1,a_1=0,x_1=-1,x_2=n-1,y_1=n-1,y_2=-1),代入可得:
    (a_i=frac{(n-1)^i+(n-1)*(-1)^i}{n})
    那么就是式子(f(t)=frac{((n-1)^t+(n-1)*(-1)^t)}{n})
    然后分奇偶BSGS即可。
    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> PII;
    typedef unsigned long long ULL;
    #define x first
    #define y second
    const int N = 1e3 + 10, M = 13331;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int mod = 998244353;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    #define gcd __gcd
    
    unordered_map<int, int> Hash;
    
    LL kpow(LL a, LL n) {
        LL res = 1;
        while(n) {
            if(n & 1) res = res * a % mod;
            n >>= 1;
            a = a * a % mod;
        }
        return res;
    }
    
    LL bsgs(LL a, LL b, LL p) {
        Hash.clear();
        a %= p; b %= p;
        if(b == 1) return 0;
        int k = sqrt(p) + 1;
        for(int i = 0, j = b % p; i < k; i++) {
            Hash[j] = i;
            j = (LL)j * a % p;
        }
        int ak = kpow(a, k);
        for(int x = 1, num = ak; x <= k; x++) {
            if(Hash.count(num)) return x * k - Hash[num];
            num = (LL)num * ak % p;
        }
        return -1;
    }
    
    void solve() {
        LL n, x;
        scanf("%lld%lld", &n, &x);
        if(x == 1) puts("0");
        else if(x == 0) puts("1");
        else {
            LL tmp = x;
            x = 1LL * x * n % mod + (n - 1);
            x = (x + mod) % mod;
            LL res = bsgs(n - 1, x, mod);
            if(res % 2 == 0) res = -1;
    
            x = tmp;
            x = 1LL * x * n % mod - (n - 1);
            x = (x + mod) % mod;
            LL ans = bsgs(n - 1, x, mod);
            if(ans & 1) ans = -1;
    
            if(res == ans && res == -1) puts("-1");
            else if(res == -1) printf("%lld
    ", ans);
            else if(ans == -1) printf("%lld
    ", res);
            else printf("%lld
    ", min(res, ans));
        }
    }
    
    int main() {
        #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        #endif // ONLINE_JUDGE
    
        int t; cin >> t; while(t--)
        solve();
        return 0;
    }
    
  • 相关阅读:
    Redis扩展功能
    Redis持久化
    redis-通讯协议及事件处理机制
    Redis-数据类型与底层数据结构
    分布式集群架构场景化解决方案
    MySQL-运维和第三方工具
    缓存原理&设计
    MySQL性能优化
    MySQL高级-日志常用的工具等等
    Mysql高级——优化
  • 原文地址:https://www.cnblogs.com/ZX-GO/p/15039734.html
Copyright © 2011-2022 走看看