广义Fibonacci数列找循环节

遇到了2019ICPC南昌赛区的网络赛的一道题,fn=3*fn-1+2*fn-2,有多次询问求fn。总结起来其实就是在模P意义下,O(1)回答广义斐波那契额数列的第n项,可以说是一道模板题了。

这道题的解法有两种:①求出通项公式之后,用二次剩余+优化快速幂(可以k进制快速幂或者把快速幂分块)解决。②求出模P意义下的递推结果的循环节,然后给矩阵分块加速递推。

看到大佬说方法一因为受到二次剩余的局限(求出的根号可能在模P意义下开不了)并不是十分通用,这里就只提到了第二张办法。

首先是怎么求广义斐波那契额数列模P意义下的循环节呢?

这里给出https://blog.csdn.net/code92007/article/details/98109917这位大佬的办法

 如果P是素数的话会简单一些

ok,这道题求出循环节是(P-1)/2=499122176之后,因为有多组询问所以我们得想办法O(1)回答询问,关键在于怎么快速计算中间矩阵mat的n次幂mat^n,这里要用到一个矩阵分块的办法。

我们令块大小为kd=sqrt(循环节大小),那么我们让S数组计算mat^1->mat^kd,然后我们用P数组计算mat^kd,mat^2kd,mat^3kd....->mat^kd*kd,容易看到这个可以O(sqrt(n))计算得到,然后对于mat^n答案就是mat^(n%kd)*mat(n/kd)=S[n%kd]*P[n/kd],就可以O(1)得到了。

那么到这里此题可解了。但是要注意有些题会有卡常的情况,注意尽量少用Longlong(只在中间相乘用),加法用快速加......

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e7+10;
const LL MOD=998244353;
int qmod(int t) { return t<MOD ? t : t-MOD; }
struct matrix{
    int m[3][3];
    matrix() { memset(m,0,sizeof(m)); }
    friend matrix operator*(matrix a,matrix b) {
        matrix res;
        for (int i=1;i<=2;i++) for (int j=1;j<=2;j++) for (int k=1;k<=2;k++)
            res.m[i][j]=qmod(res.m[i][j]+(LL)a.m[i][k]*b.m[k][j]%MOD);
        return res;
    }
};
LL Q,n,kd,ans[N],Ans; 

matrix c,S[100000],P[100000];  //分别是初始,小块,大块
void prework() {
    S[0].m[1][1]=1; S[0].m[1][2]=0; S[0].m[2][1]=0; S[0].m[2][2]=1; P[0]=S[0];
    S[1].m[1][1]=0; S[1].m[1][2]=2; S[1].m[2][1]=1; S[1].m[2][2]=3;
    for (int i=2;i<=kd;i++) S[i]=S[i-1]*S[1];
    P[1]=S[kd];
    for (int i=2;i<=kd;i++) P[i]=P[i-1]*P[1];
    c.m[1][1]=0; c.m[1][2]=1; c.m[2][1]=0; c.m[2][2]=0;
}

LL solve(LL n) {
    matrix ret=c*S[n%kd]*P[n/kd];
    return ret.m[1][1];
}

int main()
{
    kd=(LL)sqrt(MOD); prework();
    cin>>Q>>n;
    for (int i=1;i<=Q;i++) {
        ans[i]=solve(n%499122176);
        Ans=Ans^ans[i];
        n=n^(ans[i]*ans[i]);
    }
    cout<<Ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/clno1/p/11516498.html

时间: 2024-10-19 08:51:37

广义Fibonacci数列找循环节的相关文章

UVA 11582 Colossal Fibonacci Numbers! 找循环节

注意n=1的情况 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #inc

特征根法求通项+广义Fibonacci数列找循环节 - HDU 5451 Best Solver

Best Solver Problem's Link Mean: 给出x和M,求:(5+2√6)^(1+2x)的值.x<2^32,M<=46337. analyse: 这题需要用到高中的数学知识点:特征根法求递推数列通项公式. 方法是这样的: 对于这题的解法: 记λ1=5+2√6,λ2=5-2√6,则λ1λ2=1,λ1+λ2=10 根据韦达定理可以推导出:λ1,λ2的特征方程为 x^2-10x+1=0 再使用该特征方程反向推导出递推公式为:a[n]=10*a[n-1]-a[n-2] 再由特征根

广义Fibonacci数列模n的循环节

见这里:http://blog.csdn.net/ACdreamers/article/details/25616461 有详细的分析推理 只找出了循环节的上限,设 f[n] = (af[n - 1] + b[n - 2])%P,设序列a ={ f[1], f[2] }, 考虑t项后, b ={ f[t + 1], f[t + 2] }, 当t = p * p + 1时, 最多可以产生p * p + 1个不同的序列,其中至少会有一个与a相同, 而一旦与a相同,那么后面的项也会与a后面的项一样,所

HDU 4857 Couple doubi(找循环节)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4861 解题报告:桌子上有k个球 ,第i个球的价值wi = 1^i+2^i+...+(p-1)^i (mod p),现在两个人轮流取,如果第一个取的人最后得到的价值总和最大,输出YES,否则 输出NO . k和p的范围都很大,如果都算出来那是不可能的,所以一定是有规律的,所以我把前面的几个打表看了一下,果然有规律,第1.2.3.......(p-2),(p-1)个球的价值分别是: 0,0,0.....

[BestCoder Round #7] hdu 4985 Little Pony and Permutation (找循环节)

Little Pony and Permutation Problem Description As a unicorn, the ability of using magic is the distinguishing feature among other kind of pony. Being familiar with composition and decomposition is the fundamental course for a young unicorn. Twilight

HDU 3746 Cyclic Nacklace (KMP找循环节)

Problem Description CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, without any surprise, there are only 99.9 yuan left. he is too distressed and thinking about how to tide over the last days. Bein

hdu1005 Number Sequence(找循环节)

题目链接: huangjing 题意: 就是给了一个公式,然后求出第n项是多少... 思路: 题目中n的范围实在是太大,所以肯定直接递推肯定会超时,所以想到的是暴力打表,找循环节,但是也不是那么容易发现啊,所以这时候分析一下,因为最后都会mod7,所以总共有7X7总情况,即A 0,1,2,3,4,5,6,7,B也是如此,所以循环节为49,这么这个问题就解决了... 题目: Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memo

uva 11582(大fib,打表找循环节)

f (0) = 0 and f (1) = 1 f (i+2) = f (i+1) + f (i)  for every i ≥ 0 Sample input three integers a,b,n where 0 ≤ a,b < 264 (a and b will not both be zero) and 1 ≤ n ≤ 1000. T a  b  n 3 1 1 2 2 3 1000 18446744073709551615 18446744073709551615 1000 Sampl

NYOJ 427 &amp; HDU 1005 Number Sequence(找循环节)

[题目链接]click here~~ [题目大意]已经 f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.求f(n), [解题思路]:此题是大三届的一场比赛题,前几天做了下,结果是不忍直视啊,wa了几乎一页了,最开始想的是用矩阵快速幂,但是想了想,取模数才不到10,7 7=49,也就是说最大结果不超过49种可能,直接模拟递推式试试,结果发现不行,后来想到了用循环节,不难想到: 如果结果有两个答案连着 =1,则后面的全部和