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 2256 Problem of Precision

之后需要知道如何对指数 进行取模简化,问题是具体Mod 多少?

套路是mod (M-1)*(M+1) ,具体证明详见:http://blog.csdn.net/acdreamers/article/details/25616461

到这里指数取模之后,之后跑矩阵快速幂即可;

细节: 前面矩阵快速幂原本只是跑指数-1次,正好把1抵消了;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define pb push_back
#define MK make_pair
#define A first
#define B second
#define clear0 (0xFFFFFFFE)
#define inf 0x3f3f3f3f
#define eps 1e-8
#define zero(x) (((x)>0?(x):-(x))<eps)
#define bitnum(a) __builtin_popcount(a)
#define lowbit(x) (x&(-x))
#define K(x) ((x)*(x))
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
template<typename T>
void read1(T &m)
{
    T x = 0,f = 1;char ch = getchar();
    while(ch <‘0‘ || ch >‘9‘){ if(ch == ‘-‘) f = -1;ch=getchar(); }
    while(ch >= ‘0‘ && ch <= ‘9‘){ x = x*10 + ch - ‘0‘;ch = getchar(); }
    m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
    if(a>9) out(a/10);
    putchar(a%10+‘0‘);
}
inline ll gcd(ll a,ll b){ return b == 0? a: gcd(b,a%b); }
inline ll lcm(ll a,ll b){ return a/gcd(a,b)*b; }
template<class T1, class T2> inline void gmax(T1& a, T2 b){ if(a < b) a = b;}
template<class T1, class T2> inline void gmin(T1& a, T2 b){ if(a > b) a = b;}
int mod;
struct Matrix{
    int row, col;
    ll m[10][10];
    Matrix(int r,int c):row(r),col(c){ memset(m, 0, sizeof(m)); }

    bool unitMatrix(){
        if(row != col) return false;
        for(int i = 0;i < row;i++) //方阵才有单位矩阵;
                m[i][i] = 1;
        return true;
    }
    Matrix operator *(const Matrix& t){
        Matrix res(row, t.col);
        for(int i = 0; i < row; i++)
            for(int j = 0;j < t.col;j++)
                for(int k = 0; k < col; k++)
                    res.m[i][j] = (res.m[i][j] + m[i][k]*t.m[k][j])% mod;
        return res;
    }
    void print(){
        for(int i = 0;i < row; i++){
            for(int j = 0;j < col; j++)
                printf("%lld ",m[i][j]);
            puts("");
        }
    }
};

Matrix pow(Matrix a, ll n)
{
    Matrix res(a.row, a.col);
    res.unitMatrix();
    while(n){
        if(n & 1) res = res*a;
        a = a*a;
        n >>= 1;
    }
    return res;
}
ll POW(ll a,int n, ll mod)
{
    ll ans = 1;
    while(n){
        if(n&1) ans = (ans*a)%mod;
        a = a*a%mod;
        n >>= 1;
    }
    return ans;
}
int main()
{
    //freopen("data.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    Matrix mat(2,2);
    mat.m[0][0] = 5, mat.m[0][1] = 12;
    mat.m[1][0] = 2, mat.m[1][1] = 5;
    int T, kase = 1;
    scanf("%d",&T);
    while(T--){
        int n;
        read2(n, mod);
        ll MOD = 1LL*(mod-1)*(mod+1);
        MOD = POW(2,n,MOD);
        Matrix res = pow(mat, MOD);
        //res.print();
        Matrix tmp(2,1);
        tmp.m[0][0] = 5, tmp.m[1][0] = 2;
        res = res*tmp;
        printf("Case #%d: %d\n",kase++, (2*res.m[0][0]-1)% mod);
    }
    return 0;
}

ps: 这道题循环节较小,直接求解循环节也可以A;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define pb push_back
#define MK make_pair
#define A first
#define B second
#define clear0 (0xFFFFFFFE)
#define inf 0x3f3f3f3f
#define eps 1e-8
#define zero(x) (((x)>0?(x):-(x))<eps)
#define bitnum(a) __builtin_popcount(a)
#define lowbit(x) (x&(-x))
#define K(x) ((x)*(x))
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
template<typename T>
void read1(T &m)
{
    T x = 0,f = 1;char ch = getchar();
    while(ch <‘0‘ || ch >‘9‘){ if(ch == ‘-‘) f = -1;ch=getchar(); }
    while(ch >= ‘0‘ && ch <= ‘9‘){ x = x*10 + ch - ‘0‘;ch = getchar(); }
    m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
    if(a>9) out(a/10);
    putchar(a%10+‘0‘);
}
inline ll gcd(ll a,ll b){ return b == 0? a: gcd(b,a%b); }
template<class T1, class T2> inline void gmax(T1& a, T2 b){ if(a < b) a = b;}
template<class T1, class T2> inline void gmin(T1& a, T2 b){ if(a > b) a = b;}

ll pow(ll a,uint n,int mod)
{
    ll ans = 1;
    while(n){
        if(n&1) ans = (ans*a)%mod;
        a = a*a%mod;
        n >>= 1;
    }
    return ans;
}
const int maxn = 463370;
int F[maxn];
int main()
{
    //freopen("data.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T, kase = 1;
    /*double d1 = 5+2*sqrt(6), d2 = 5 - 2*sqrt(6);
    rep1(i,1,10){
        printf("%.5f\n",pow(d1,i)+pow(d2,i));
    }*/
    scanf("%d",&T);
    while(T--){
        uint x, mod;
        read2(x,mod);
        F[0] = 10%mod, F[1] = 98%mod;
        ll cycle = -1;
        for(int i = 2; ; i++){
            F[i] = (10*F[i-1] - F[i-2]+ mod)% mod;
            if(F[i] == F[1] && F[i-1] == F[0]){
                cycle = i-1;
                break;
            }
        }
        int p = pow(2,x, cycle);
        printf("Case #%d: %d\n",kase++, F[p]-1);
    }
    return 0;
}

时间: 2024-08-26 15:13:23

hdu 5451 Best Solver 矩阵循环群+矩阵快速幂的相关文章

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 4704 Sum (费马小定理+快速幂)

//(2^n-1)%mod //费马小定理:a^n ≡ a^(n%(m-1)) * a^(m-1)≡ a^(n%(m-1)) (mod m) # include <stdio.h> # include <algorithm> # include <string.h> # define mod 1000000007 using namespace std; __int64 pow(__int64 n) { __int64 p=1,q=2; while(n) { if(n%

hdu 2817 A sequence of numbers(快速幂取余)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2817 题目大意:给出三个数,来判断是等差还是等比数列,再输入一个n,来计算第n个数的值. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #define m 200907 5 6 using namespace std; 7 8 __int64 fun(__int64 j,__int64 k) 9

【矩阵快速幂+循环节】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

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 4365 正方形格子涂色中心对称轴对称的涂法有多少种-思维-(矩阵坐标关系&amp;快速幂取模)

题意:n*n的格子,涂色,有k种颜料,必须满足旋转任意个90度和翻转之后图片的样子不变,现在已经有m个格子涂过色了,问还有多少种涂法满足上述条件. 分析: 满足上述对称条件,那么涂色的种类问题我们可以放在正方形的一个角来做,因为一个角确定了其他角的颜色也就确定了. 以左上角的下半角为例.共有1+2+....+(n+1)/2个格子,然后记录涂过色的格子对应到这个三角形里的格子数目,用tot来记录,即每输入一个涂过色的格子的坐标我们就在这个三角形里找与之对应的坐标,用vis[][]数组标记是否已经计

矩阵乘法、快速幂

1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 #include <cstring> 5 using namespace std; 6 // 矩阵的STL实现 7 typedef vector<int> vec; 8 typedef vector<vec> mat; 9 typedef long long ll; 10 const int MOD = 10

poj3613:Cow Relays(倍增优化+矩阵乘法floyd+快速幂)

Cow Relays Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7825   Accepted: 3068 Description For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout

HDU 5451 Best Solver(fibonacci)

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