• [洛谷P5136]sequence


    题目大意:有$T(Tleqslant10^5)$组询问,每次求$A_n(nleqslant10^{18})$:
    $$
    A_n=leftlceilleft(dfrac{sqrt5+1}2 ight)^n ight ceil
    $$
    题解:通过打表看题解发现,这个序列是$2,3,5,7,dots$,即$A_n=A_{n-1}+A_{n-2}-[nequiv0pmod2]$,题解中说可以记录三个信息矩阵快速幂一下,然后我并不会处理$[nequiv0pmod2]$(果然我最菜)

    继续看下去,他说可以构造数列$F$,$F_n=F_{n-1}+F_{n-1}(F_1=1,F_2=3)$,$A_n=F_n+(nmod2)$,这样就可以过去了,复杂度$O(2^3Tlog_2n)$

    但是这样似乎感觉不够优秀,可以把转移矩阵分块预处理出来,$nleqslant10^{18}<2^{60}$,可以$sqrt{sqrt n}$即$2^{15}$分一块,这样就可以在常数复杂度内求出一次的答案了,复杂度$O(4 imes2^3T)$

    更进一步的是,$F$为斐波那契数列,它在模一个数下有循环节,洛谷上有这么一道题,比如在$998244353$下为$1996488708$,这样就可以取模后分块,就可以只分成两块,减少常数,复杂度$O(2 imes2^3T)$(但是我跑的比上一个慢。。。加了编译指令才比上一个快

    卡点:最开始以为矩阵的右下角不会有值

    C++ Code:

    #include <cstdio>
    #include <cctype>
    #define N 65537
    const int mod = 998244353, cover = (1 << 16) - 1;
    
    namespace std {
    	struct istream {
    #define M (1 << 23 | 3)
    		char buf[M], *ch = buf - 1;
    		inline istream() { fread(buf, 1, M, stdin); }
    		inline istream& operator >> (int &x) {
    			while (isspace(*++ch));
    			for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
    			return *this;
    		}
    		inline istream& operator >> (long long &x) {
    			while (isspace(*++ch));
    			for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
    			return *this;
    		}
    #undef M
    	} cin;
    	struct ostream {
    #define M (1 << 22 | 3)
    		char buf[M], *ch = buf - 1;
    		inline ostream& operator << (int x) {
    			if (!x) {*++ch = '0'; return *this;}
    			static int S[20], *top; top = S;
    			while (x) {*++top = x % 10 ^ 48; x /= 10;}
    			for (; top != S; --top) *++ch = *top;
    			return *this;
    		}
    		inline ostream& operator << (const char x) {*++ch = x; return *this;}
    		inline ~ostream() { fwrite(buf, 1, ch - buf + 1, stdout); }
    #undef M
    	} cout;
    }
    
    struct Matrix {
    	int s00, s01, s10, s11;
    	Matrix() { }
    	Matrix(int __00, int __01, int __10, int __11) : s00(__00), s01(__01), s10(__10), s11(__11) { }
    	inline Matrix operator * (const Matrix &rhs) {
    #define M(l, r) static_cast<long long> (s##l) * rhs.s##r
    #define C(ll, lr, rl, rr) (M(ll, lr) + M(rl, rr)) % mod
    		return Matrix(C(00, 00, 01, 10), C(00, 10, 01, 11), C(10, 00, 11, 10), C(10, 01, 11, 11));
    #undef M
    #undef calc
    	}
    } base0[N], base1[N], ans(3, 1, 0, 0);
    
    void init() {
    	const Matrix I(1, 0, 0, 1);
    #define work(x) 
    	*base##x = I; 
    	for (int i = 1; i < N; ++i) base##x[i] = base##x[i - 1] * __base##x;
    	const Matrix __base0(1, 1, 1, 0); work(0);
    	const Matrix __base1 = base0[N - 1]; work(1);
    #undef work
    }
    
    int Tim;
    int main() {
    	init();
    	std::cin >> Tim;
    	while (Tim --> 0) {
    		static long long n;
    		static int res;
    		std::cin >> n; --n, n %= 1996488708;
    		res = (ans * base0[n & cover] * base1[n >> 16 & cover]).s01 + !(n & 1) - mod;
    		std::cout << res + (res >> 31 & mod) << '
    ';
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    media query不一致
    数据库设计三范式
    异步概念及使用场景
    关于webservice框架CXF的总结
    通过bash文件(shell命令)对文件进行修改
    shell命令相关问题
    shell对文本进行操作命令
    虚拟机安装系统常见问题
    安装autotools系列工具
    Centos和Ubuntu下打包项目
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10356832.html
Copyright © 2020-2023  润新知