zoukankan      html  css  js  c++  java
  • 《入门经典》——9.2

      Uva11582:

      基于斐波那契数列,给出a,b,mod,让你求解f(a^b) % mod的结果。

      分析:这是一道很看基本功的简单数论题目。

    数据类型:题目给出的a、b的范围最大可以取到2^64,因此这里凡是用到a、b的运算的地方都要用ULL(unsigned long long),经过调试显示long long这个数据类型都不够。

      算法分析:本身斐波那契数列在一定项之后就变得异常大,结合同余运算的性质,因此这里我们考虑直接基于余数进行迭代求余。 而由于a、b的取值范围,我们显然不能打表打到a^b,因此我们推测取余结果必然存在周期性。

      进一步更详细的分析周期性存在的合理性:令F(i) = f(i) % mod , 这里f(i)是斐波那契数列。我们得到F(n)的线性序列,我们从二元组<F(i),F(i+1)>来看,在根据递推公式往后生成的时候,一旦<F(i),F(i+1)>曾经出现过,这就表明余数的线性序列的周期是i-1。而二元组最多有mod x mod个,因此F(i)的序列长度超过mod x mod之后,必然会出现周期性。

      总结起来,在这里处理数据巨大的技巧,归结为下面几个方面:

    1. 将f(i)映射到F(i) = f(i) % mod.
    2. 在证明了F(i)分布的周期性必然存在之后,寻找F(i)分布的周期性。
    3. 利用快速幂取模找到a^b处于一个周期中那个位置,即计算a^b % M.其中M是F(i)分布的周期M.

      简单的参考代码如下:

     #include<cstdio>
    
    #include<vector>
    
    #include<algorithm>
    
    #include<iostream>
    
    using namespace std;
    
    const int maxn = 1001;
    
    vector<int>f[maxn];
    
    typedef unsigned long long ULL;
    
    void init()
    
    {
    
         for(int i = 2;i <= 1000;i++)
    
         {
    
              int mod = i;
    
               int a = 0 , b =  1 , c = (a+b)% mod;
    
               f[i].push_back(a);
    
               f[i].push_back(b);
    
               f[i].push_back(c);
    
     
    
              while(!(b == 0 && c == 1))
    
               {
    
                   a = b;
    
                   b = c;
    
                   c = (a % mod +b % mod) % mod;
    
                   f[i].push_back(c);
    
               }
    
               f[i].pop_back();
    
               f[i].pop_back();
    
         }
    
    }
    
     
    
     ULL quick_mod(ULL a,ULL b, int _m)
    
     {
    
        ULL ans = 1;
    
        while(b){
    
            if(b&1){
    
                ans = (ans%_m) * (a%_m) % _m;
    
                b--;
    
            }
    
            b /= 2;
    
            a = (a%_m)*(a%_m)%_m;
    
        }
    
        return ans;
    
    }
    
     
    
    ULL n , m ;
    
    int main()
    
    {
    
        int t;
    
     
    
        int  Mod;
    
        init();
    
        scanf("%d",&t);
    
        while(t--)
    
        {
    
           cin >> n >> m >> Mod;
    
            if(Mod == 1)  {printf("0
    ");continue;}
    
            int _m = f[Mod].size();
    
            ULL temp = quick_mod(n , m , _m);
    
            printf("%d
    ",f[Mod][temp]);
    
        }
    
    }
  • 相关阅读:
    Babel的安装和使用
    ECMAScript 6 和数组的新功能
    网站首页被降权后怎么快速处理
    赫然:怎样学习seo优化技术
    浅谈互联网页面价值
    ZERO:从搜索用户来看SEO
    李彦宏:论搜索引擎三个定律
    焦大:seo该研究用户需求还是搜索算法
    GA教程:使用自定义变量来扩展高级细分
    焦大:做SEO应该研究的用户需求的方向
  • 原文地址:https://www.cnblogs.com/rhythmic/p/5833111.html
Copyright © 2011-2022 走看看