(5.20-21祝有对象的好朋友99999鸭!!!)Colossal Fibonacci Numbers! UVA - 11582

首先,斐波那契数列每一个数模一个特定的数会出现循环节现象:

斐波那契数列Mod 一个数N会得到一个新的数列,根据同余可以得知,这个数列中的数会出现循环。例如: 
F (mod 4) = 0 1 1 2 3 1 … 
F (mod 5) = 0 1 1 2 3 0 3 3 1 4 0 4 4 3 2 0 2 2 4 1 …

后面的数会出现循环,因此Fib Mod 4的循环节长度是6,Fib Mod 5的循环节长度是20。 

-->https://blog.csdn.net/zhuangmezhuang/article/details/52627308

其次,这个循环节的范围(鸽笼原理):

因为f(i)=f(i-1)+f(i-2), 所以如果有   f(x-1)==f(i-1)&&f(x)==f(i) 且x!=i ,那么势必会出现循环。

n很小,在[1,n^2+2]内必须会出现这样一对x和i,即周期一定<=n^2  (鸽笼原理)。

https://blog.csdn.net/yskyskyer123/article/details/50962056?utm_source=blogxgwz8

鸽笼原理(抽屉原理)就是"如果有五个鸽子笼,养鸽人养了6只鸽子,那么当鸽子飞回笼中后,至少有一个笼子中装有2只鸽子。"这个简单的事实就是著名的鸽笼原理,在我们国家更多地称为抽屉原理。有n+1件或n+1件以上的物品要放到n个抽屉中,那么至少有一个抽屉里有两个或两个以上物品.

最后,快速幂取模:

参考--->https://www.cnblogs.com/Howe-Young/p/4097277.html

ab mod c = (a mod c)b mod c

                                      

上面公式为下面公式的引理,即积的取余等于取余的积的取余。

                                       

证明了以上的公式以后,我们可以先让a关于c取余,这样可以大大减少a的大小

快速幂算法依赖于以下公式:

                                      

#include<iostream>
using namespace std;
typedef unsigned long long ull;
///a,b<2^64用无符号长整形(2^64-1)
int fibonacci[1000000];///最大不超过n*n
int quick_pow(ull a,ull b,int mod)
{///快速幂+每步取模
    ull ans=1,base=a%mod;
    while(b)
    {
        if(b&1)ans=(ans*base)%mod;
        base=(base*base)%mod;
        b>>=1;
    }
    return ans;
}
int solve(int n)
{
    fibonacci[0]=0;
    fibonacci[1]=1%n;///这里必须模一个n!!!!否则会运行错误
    for(int i=2;i<n*n;i++)
    {
        fibonacci[i]=(fibonacci[i-1] + fibonacci[i-2])%n;
        if (fibonacci[i-1]==fibonacci[0]&&fibonacci[i]==fibonacci[1])
            ///查找循环节,连续两个数和前两个数出现重复
            return i-1;///返回循环节
    }
}
int main()
{
    ull a,b;
    int n,t;
    cin>>t;
    while(t--)
    {
        cin>>a>>b>>n;
        cout<<fibonacci[quick_pow(a,b,solve(n))]<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43813697/article/details/90411602
今日推荐