HDU 5451 Best Solver(fibonacci)

感谢这道题让我复习了一遍线代,还学习了一些奇奇怪怪的数论。

二项展开以后根号部分抵消了

显然有

所以要求的答案是

如果n比较小的话,可以直接对二项式快速幂,但是这题n很大

这个问题和矩阵的特征值以及数列递推有奇怪的联系

广义的fibonacci数列的形式如下

写成矩阵形式就是

有一个奇怪的结论:

其中lambda1,lambda2是递推矩阵的特征值,此处只讨论lambda1!=lambda2的情况。

这个奇怪的结论其实很容易证明,

根据以上结果,利用矩阵的数乘和分配律然后归纳就可以完整得到结论

令lambda1=p,lambda2=q,可以求出a和b,答案就在递推的第n项

然后通过找循环节减小n

m是素数时一般的做法:http://blog.csdn.net/ACdreamers/article/details/25616461

费马小定理和欧拉准则不明觉厉。。。

此题所有的m循环节都小,直接暴力,然后记忆化

lambda1!=lambda2,所以A一定可以对角化,而A^n就可以表示为

对应特征值

并且有

所以对A矩阵快速幂以后算出迹减1就是答案

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

struct Matrix
{
    int e[2][2];
    int* operator[](int p){
        return e[p];
    }
};

ll Mod;
Matrix operator *(Matrix &A, Matrix &B)
{
    Matrix R;
    for(int i = 0; i < 2; i++){
        for(int j = 0; j < 2; j++){
            R[i][j] = 0;
            for(int k = 0; k < 2; k++){
                R[i][j] = (R[i][j] + (ll)A[i][k]*B[k][j]+Mod)%Mod;
            }
        }
    }
    return R;
}

Matrix Matrix_pow(Matrix A,ll p)
{
    Matrix R;
    for(int i = 0; i < 2; i++){
        for(int j = 0; j < 2; j++){
            R[i][j] = i==j?1:0;
        }
    }
    while(p){
        if(p&1) R = R*A;
        A = A*A;
        p>>=1;
    }
    return R;
}

ll qPow(ll a,ll p,ll mod)
{
    ll ret = 1;
    while(p){
        if(p&1) ret = (ret*a)%mod;
        a = (a*a)%mod;
        p >>= 1;
    }
    return ret;
}

const int maxm = 46337+5;
int r[maxm],f[maxm];

int main()
{
    //freopen("in.txt","r",stdin);
    int T, kas = 0; scanf("%d",&T);
    while(T--){
        ll x; scanf("%I64d%I64d",&x,&Mod);
        if(!r[Mod]){
            f[0] = 2; f[1] = 10;
            for(int i = 2; ;i++){
                f[i] = (10LL*f[i-1]-f[i-2]+Mod)%Mod;
                if(f[i] == f[1] && f[i-1] == f[0]){ r[Mod] = i-1; break; }
            }
        }
        Matrix A;
        A[0][0] = 10%Mod; A[0][1] = Mod-1; A[1][0] = 1; A[1][1] = 0;
        auto ans = Matrix_pow(A,(qPow(2,x,r[Mod])+1)%r[Mod]);
        printf("Case #%d: %d\n",++kas,(ans[0][0]+ans[1][1]+Mod-1)%Mod);
    }
    return 0;
}
时间: 2024-08-11 03:29:35

HDU 5451 Best Solver(fibonacci)的相关文章

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 1045 - Fire Net (最大独立集)

题意:给你一个正方形棋盘.每个棋子可以直线攻击,除非隔着石头.现在要求所有棋子都不互相攻击,问最多可以放多少个棋子. 这个题可以用搜索来做.每个棋子考虑放与不放两种情况,然后再判断是否能互相攻击来剪枝.最后取可以放置的最大值. 这里我转化成求最大独立集来做. 首先将每个空地编号,对于每个空地,与该位置可以攻击到的空地连边.找最多的空地使得不互相攻击,即求该图的最大独立集.与搜索做法基本一致,但是说法略有不同. 1 #include<iostream> 2 #include<cstring

hdu oj1102 Constructing Roads(最小生成树)

Constructing Roads Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13995    Accepted Submission(s): 5324 Problem Description There are N villages, which are numbered from 1 to N, and you should

HDU 1863 畅通工程 (最小生成树)

Problem Description 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本.现请你编写程序,计算出全省畅通需要的最低成本. Input 测试输入包含若干测试用例.每个测试用例的第1行给出评估的道路条数 N.村庄数目M ( < 100 ):随后的 N 行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间

hdu 3650 Hot Expo(贪心)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3650 --------------------------------------------------------------------------------------------------------------------------------------------

hdu 4970 Killing Monsters(数学题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4970 Problem Description Kingdom Rush is a popular TD game, in which you should build some towers to protect your kingdom from monsters. And now another wave of monsters is coming and you need again to k

HDU 3572 Task Schedule(ISAP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3572 题意:m台机器,需要做n个任务.第i个任务,你需要使用机器Pi天,且这个任务要在[Si  ,  Ei]区间内完成才有效.对于一个任务,只能由一个机器来完成,一个机器同一时间只能做一个任务.当然,一个任务可以分成几段不连续的时间来完成.问,能否做完全部任务. 题意很清晰,也就是判断是否是满流. 对于网络流问题,模板大家都有,关键在于如何建图(详见资料) 思路:今天问了龙哥,对建图有了一定的了解,

hdu 1728 逃离迷宫 (BFS)

逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 14376    Accepted Submission(s): 3458 Problem Description 给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方

HDU 4563 御剑术I(背包)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4563 题意:一个点开始在原点.有n个命令.第i个命令施加到这个点时,这个点的速度为(Vxi,Vyi),即在x方向的速度为Vxi,在y方向的速度为 Vyi.并且这个命令施加到点时之前的速度全部消失.每种命令最多使用一次.问在x方向走长度为m时在y方向的最大高度是多少?每种命令只能在整数时刻施 加. 思路:首先,每种命令使用的先后顺序显然是没有关系的.除了最后一个施加的命令,之前的命令必然都是使用了整数