zoukankan      html  css  js  c++  java
  • CF1106F Lunar New Year and a Recursive Sequence 线性递推 + k次剩余

    已知(f_i = prod limits_{j = 1}^k f_{i - j}^{b_j};mod;998244353),并且(f_1, f_2, ..., f_{k - 1} = 1)(f_k = a),已知(f_n = m),试求(a)

    易知(f_n = f_k^p)

    对于(p)满足递推式(g[i] = sum limits_{j = 1}^k b[j] * g[i - j])

    这是常系数线性递推,由于(k leq 100),因此矩阵快速幂即可

    那么问题就变为了(f_k^p = m(;mod;998244353)),求(f_k)

    由于(998244353)的原根为(3),因此把(m)离散之后,可以写出方程

    (f_k = 3^s(mod;998244353))(m = 3^t),那么有(3^{sp} = 3^t (mod;998244353))

    由欧拉定理(sp = t(mod;998244352)),然后解一下这个同余方程

    有解则输出,无解就无解

    复杂度(O(k^3 log n + sqrt{998244353}))


    #include <map>
    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define de double
    #define ll long long
    #define ri register int
    #define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
    #define drep(io, ed, st) for(ri io = ed; io >= st; io --)
    
    #define gc getchar
    inline int read() {
    	int p = 0, w = 1; char c = gc();
    	while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
    	while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
    	return p * w;
    }
    	
    const int sid = 105;
    const int mod = 998244353;
    const int g = 3;
    
    inline int mul(int a, int b) { return 1ll * a * b % mod; }
    inline int fp(int a, int k) {
    	int ret = 1;
    	for( ; k; k >>= 1, a = mul(a, a))
    		if(k & 1) ret = mul(ret, a);
    	return ret;
    }
    
    int n, m, k, b[sid];
    struct mtx {
        int f[sid][sid];
        mtx() {}
        mtx(int flag) {
            if(flag == 0) {
                for(int i = 0; i < k; i ++)
                for(int j = 0; j < k; j ++)
                f[i][j] = 0;
            } 
            if(flag == 1) {
                for(int i = 0; i < k; i ++)
                for(int j = 0; j < k; j ++)
                f[i][j] = (i == j) ? 1 : 0;
            }
        }
        int* operator [] (const int x) {
            return f[x];
        }
        friend mtx operator * (mtx a, mtx b) {
           mtx c(0);
            for(int i = 0; i < k; i ++)
            for(int j = 0; j < k; j ++)
            for(int p = 0; p < k; p ++)
            c[i][j] = (c[i][j] + 1ll * a[i][p] * b[p][j] % (mod - 1)) % (mod - 1);
            return c;
        }
    } A, B;
    	
    inline mtx fp(mtx a, int k) {
    	mtx ret(1);
    	for( ; k; k >>= 1, a = a * a)
    		if(k & 1) ret = ret * a;
    	return ret;
    }
    	
    map <int, int> H;
    inline int BSGS(int A, int B) {
    	H.clear(); H[1] = 0;
    	int Ai = 1, Aj = 1, m = ceil(sqrt(mod));
    	for(ri i = 1; i < m; i ++) Ai = 1ll * Ai * A % mod, H[1ll * Ai * B % mod] = i;
    	Ai = 1ll * Ai * A % mod;
    	for(ri i = 1; i <= m; i ++) {
    		Aj = 1ll * Aj * Ai % mod;
    		if(H[Aj]) return 1ll * i * m - H[Aj];
    	}
    }
    
    inline int gcd(int a, int b) {
    	return b ? gcd(b, a % b) : a;
    }
    
    inline void exgcd(int &x, int &y, int a, int b) {
    	if(!b) { x = 1; y = 0; return; }
    	exgcd(y, x, b, a % b); y -= a / b * x;
    }
    	
    inline void Solve() {
    	A[0][k - 1] = 1;
    	rep (i, 0, k - 1) B[i][k - 1] = b[k - i];
    	rep (i, 0, k - 2) B[i + 1][i] = 1;
    	
    	A = A * fp(B, n - k);
    
    	int p = A[0][k - 1], t = BSGS(g, m);
    	if(t % gcd(p, mod - 1)) printf("-1
    ");
    	else {
    		int gd = gcd(p, mod - 1);
    		int x, y, a = p, b = mod - 1;
    		t /= gd; a /= gd; b /= gd;
    		exgcd(x, y, a, b); 
    		x = (x + mod - 1) % (mod - 1);
    		x = 1ll * x * t % (mod - 1);
    		printf("%d
    ", fp(g, x));
    	}
    }
    	
    int main() {
    	k = read();
    	rep(i, 1, k) b[i] = read();
    	n = read(); m = read();
    	Solve();
    	return 0;
    }
    
  • 相关阅读:
    IE无法打开internet网站已终止操作的解决的方法
    iOS IAP教程
    splice()函数的使用方法
    socket通信简单介绍
    puppet安装和使用
    解惑:NFC手机怎样轻松读取银行卡信息?
    深入浅出谈开窗函数(一)
    TCP/IP协议,HTTP协议
    动态规划0—1背包问题
    栈的链式存储结构及其基本运算的实现
  • 原文地址:https://www.cnblogs.com/reverymoon/p/10344706.html
Copyright © 2011-2022 走看看