zoukankan      html  css  js  c++  java
  • ACM学习历程—HDU 5451 Best Solver(Fibonacci数列 && 快速幂)(2015沈阳网赛1002题)

    Problem Description
    The so-called best problem solver can easily solve this problem, with his/her childhood sweetheart.

    It is known that y=(5+2√6)^(1+2^x).
    For a given integer x (0x<2^32) and a given prime number M (M46337) , print [y]%M . ([y] means the integer part of y )
     
    Input
    An integer T (1<T1000) , indicating there are T test cases.
    Following are T lines, each containing two integers x and M , as introduced above.
     
    Output
    The output contains exactly T lines.
    Each line contains an integer representing [y]%M .
     
    Sample Input
    7
    0 46337
    1 46337
    3 46337
    1 46337
    21 46337
    321 46337
    4321 46337
     
    Sample Output
    Case #1: 97
    Case #2: 969
    Case #3: 16537
    Case #4: 969
    Case #5: 40453
    Case #6: 10211
    Case #7: 17947

    题目大意就是求那个式子y=(5+2√6)^(1+2^x)。

    考虑(5+2√6)^n和(5-2√6)^n;

    分别设为A和B,

    自然A*B=1

    考虑A+B,发现奇数次幂的根号消掉了,于是是个整数。

    由因为A>1,自然B<1所以说A的小数部分就是1-B,所以A的整数部分就是A+B-1。

    于是就是求A+B,便能得到结果。

    而这个式子跟特征根求解的一次线性递推式的结果很像。

    于是考虑x^2+bx+c=0这个特征方程,跟为5+2√6和5-2√6。

    得b=-10,c=1。

    于是递推式为f(n+2)=10f(n+1)-f(n)。

    然后本地打表发现,不管模范围内的任何素数,这个序列的循环节都不是很大。

    于是考虑直接暴力循环节,不过记忆化下来。

    然后就是考虑2^x模循环节的结果即可,这个用快速幂。

    复杂度是O(r+logx),其中r为循环节大小。

    题解中通过结论 (p^2- p)(p^2-1)为循环节使用矩阵快速幂.

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #define LL long long
    
    using namespace std;
    
    const int maxM = 47000;
    int x, m, r[maxM], f[maxM];
    
    void init()
    {
        if (r[m] != -1)
            return;
        f[0] = 2%m;
        f[1] = 10%m;
        for (int i = 2;; ++i)
        {
            f[i] = ((10*f[i-1]-f[i-2])%m+m)%m;
            if (f[i-1] == f[0] && f[i] == f[1])
            {
                r[m] = i-1;
                break;
            }
        }
    }
    
    //快速幂m^n
    int quickPow(LL x, int n, int mm)
    {
        int a = 1;
        while (n)
        {
            a *= n&1 ? x : 1;
            a %= mm;
            n >>= 1 ;
            x *= x;
            x %= mm;
        }
        return a;
    }
    
    void work()
    {
        int k, ans;
        k = quickPow(2, x, r[m]);
        k = (k+1)%r[m];
        f[0] = 2%m;
        f[1] = 10%m;
        for (int i = 2; i <= k; ++i)
            f[i] = ((10*f[i-1]-f[i-2])%m+m)%m;
        ans = (f[k]-1+m)%m;
        printf("%d
    ", ans);
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        memset(r, -1, sizeof(r));
        int T;
        scanf("%d", &T);
        for (int times = 0; times < T; ++times)
        {
            printf("Case #%d: ", times+1);
            scanf("%d%d", &x, &m);
            init();
            work();
        }
        return 0;
    }
  • 相关阅读:
    正则表达式(验证账号密码邮箱身份证)
    JS Fetch
    事件流动
    JS DOM和BOM
    CSS的定位
    For each...in / For...in / For...of 的解释和例子
    CSS的gridlayout
    CSS position属性
    CSS的颜色
    twelfth week
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4822086.html
Copyright © 2011-2022 走看看