HDU 5451

题目要求:y = (5 + 2√6)1+2^x

设An=(5 + 2√6)n,Bn=(5 - 2√6)n

Cn = An + Bn

显然Cn是正整数,且Bn是小于1的

所以我们所求的答案其实就是Cn - 1

通过推导:

Cn * [(5 + 2√6) + (5 - 2√6)] =

((5 + 2√6)n + (5 - 2√6)n) * [(5 + 2√6) + (5 - 2√6)] =

(5 + 2√6)n + 1 + (5 - 2√6)n + 1) + (5 + 2√6)n - 1 + (5 - 2√6)n - 1)

10 * Cn = Cn + 1 + Cn - 1

Cn + 1 = 10 * Cn - Cn-1

我们找出了递推式,然后我们发现指数特别的大,M是个素数

于是我们可以实力地打一个表

/***********************************
*                                  *
*    Auther Rhapsody               *
*    E-mail [email protected]    *
*                                  *
***********************************/
#include <set>
#include <map>
#include <cmath>
#include <deque>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#define MP make_pair
#define PB push_back

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int N = 5e6 + 7;
const int INF = 0x3f3f3f3f;

int MOD = 1e9 + 7;

int f[N];

//map <PII, int> Mapper;

int pow_mod(int x, int y, int MOD) {
    int Ans = 1;
    while (y) {
        if (y & 1)
            Ans = (LL)Ans * x % MOD;
        x = (LL)x * x % MOD;
        y >>= 1;
    }
    return Ans;
}

int find(int a, int idx, int MOD) {
    int x = pow_mod(2, a, MOD);
    x = (x + 1 - idx) % MOD;
    x = (x + MOD) % MOD;
    return idx - MOD + x;
}

int main(void) {
    int T, Test = 0;
    scanf("%d", &T);
    int a, m;
    while (T--) {
        scanf("%d%d", &a, &m);
        MOD = m;
        //Mapper.clear();
        f[0] = 2 % MOD;
        f[1] = 10 % MOD;
        //Mapper[MP(f[1], f[0])] = 1;
        int idx = 2, loop, S;
        while (true) {
            f[idx] = (f[idx - 1] * 10 - f[idx - 2]) % MOD;
            f[idx] = (f[idx] + MOD) % MOD;
            //PII t = MP(f[idx], f[idx - 1]);
            if (f[idx] != f[1] || f[idx - 1] != f[0]) {
                //Mapper[t] = idx++;
                ++idx;
                continue;
            }
            S = idx;
            loop = idx - 1;
            break;
        }
        int sum = 1;
        bool flag = true;
        for (int i = 1; i <= a; ++i) {
            sum = sum * 2;
            if (sum + 1 > S) {
                flag = false;
                break;
            }
        }
        if (flag) {
            printf("Case #%d: %d\n", ++Test, (f[sum + 1] - 1 + MOD) % MOD);
            continue;
        }
        printf("Case #%d: %d\n", ++Test, (f[find(a, S, loop)] - 1 + MOD) % MOD);
    }
    return 0;
}
时间: 2024-11-06 13:01:55

HDU 5451的相关文章

Hdu 5451 Best Solver (2015 ACM/ICPC Asia Regional Shenyang Online) 暴力找循环节 + 递推

题目链接: Hdu  5451  Best Solver 题目描述: 对于,给出x和mod,求y向下取整后取余mod的值为多少? 解题思路: x的取值为[1, 232],看到这个指数,我的心情是异常崩溃的.(吐血......) 可是仔细观察,它指数大,可是mod小啊,它吓人,可是可以暴力搞啊!! 这个题目一个难点就是要向下取整求余,详解见传送门,本题是向下取整,也就是向上取整加一. 还有就是指数太大,要找到循环节,其实由于mod小,循环节并没有太大,暴力跑就ok啦!  此刻内心是崩溃的 1 #i

hdu 5451 Best Solver 矩阵循环群+矩阵快速幂

http://acm.hdu.edu.cn/showproblem.php?pid=5451 题意:给定x    求解 思路: 由斐波那契数列的两种表示方法, 之后可以转化为 线性表示 F[n] = F[n-1] + F[n-2] ; 同时可以看出   和 是 一元二次方程的两根, a  = 1, b = -1 又是之后递推式的系数: 同理这里需要构造出两根为 和 ,这时 a = 1, b = –10 得 F[n] = 10F[n-1] – F[n-2]; (当然可以直接打表递推出关系式) 如果

hdu 5451 Best Solver(矩阵快速幂+循环节)

题意: 已知,给你整数x,和一个素数M,求[y]%M 思路: 设 (5+2√6)n=Xn+Yn*√6 Xn+Yn*√6 =(Xn-1+Yn-1*√6)*(5+2√6) => 5*Xn-1 + 12*Yn-1 + (2*Xn-1 + 5*Yn-1 )*√6 Xn =  5*Xn-1 + 12*Yn-1: Yn =  2*Xn-1 + 5*Yn-1: 然而√6还是一个大问题,解决办法: (5 - 2√6)n = Xn - Yn*√6 (5+2√6)n=Xn+Yn*√6 + Xn - Yn*√6 -

HDU 5451 广义斐波那契数列

这道题目可以先转化: 令f(1) = 5+2√6 f(2) = f(1)*(5+2√6) ... f(n) = f(n-1)*(5+2√6) f(n) = f(n-1)*(10-(5-2√6)) = 10*f(n-1)-(5-2√6)f(n-1) = 10*f(n-1) - 10/(5+2√6) f(n-1) = 10*f(n-1) - 10/(5+2√6) * (5+2√6)f(n-2) = 10*f(n-1) - f(n-2) 那么就可以写成矩阵相乘的形式了 (f(n) , f(n-1))

ACM学习历程—HDU 5451 Best Solver(Fibonacci数列 &amp;&amp; 快速幂)(2015长春网赛1007题)

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 (0≤x<2^32) and a given prime number M (M≤46337) , print [y]%M . ([y] mean

HDU 5451 Best Solver(fibonacci)

感谢这道题让我复习了一遍线代,还学习了一些奇奇怪怪的数论. 令 二项展开以后根号部分抵消了 显然有 所以要求的答案是 如果n比较小的话,可以直接对二项式快速幂,但是这题n很大 这个问题和矩阵的特征值以及数列递推有奇怪的联系 广义的fibonacci数列的形式如下 写成矩阵形式就是 有一个奇怪的结论: 其中lambda1,lambda2是递推矩阵的特征值,此处只讨论lambda1!=lambda2的情况. 这个奇怪的结论其实很容易证明, 根据以上结果,利用矩阵的数乘和分配律然后归纳就可以完整得到结

【矩阵快速幂+循环节】HDU 5451 Best Solver

通道 题意:计算(5+26√)1+2^x. 思路:循环节是(p+1)*(p-1),然后就是裸的矩阵快速幂啦. 代码: #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N = 2; int MOD; struct

特征根法求通项+广义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] 再由特征根

hdu 5451 Best Solver

很显然这是矩阵快速幂的题 但发现用矩阵快速幂,指数很大很大,没办法用欧拉降幂(傻乎乎的用欧拉降幂,欧拉降幂只是对底数为整数,做了3个小时),结果是由周期的,根据周期对指数进行降幂,然后再矩阵快速幂,最后答案减一,因为这是求的向上取整 AC code: #include <bits/stdc++.h> using namespace std; const int N = 1e6 + 10; const int M = 2; typedef long long ll; int m=2; int M