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 MOD;
struct Matrix{
    ll matrix[M][M];
};
void init(Matrix &res)
{
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<m;j++)
            res.matrix[i][j]=0;
        res.matrix[i][i]=1;
    }
}
Matrix multiplicative(Matrix a,Matrix b)
{
    Matrix res;
    memset(res.matrix,0,sizeof(res.matrix));
    for(int i = 0 ; i <m; i++)
        for(int j = 0 ; j < m ; j++)
            for(int k = 0 ; k < m; k++)
                res.matrix[i][j] = (res.matrix[i][j]+a.matrix[i][k]%MOD*b.matrix[k][j]%MOD+MOD)%MOD;
    return res;
}
Matrix pow(Matrix mx,ll m)
{
    Matrix res,base=mx;
    init(res); //初始为单位矩阵,即除主对角线都是1外,其他都是0
    while(m)
    {
        if(m&1)
            res=multiplicative(res,base);
        base=multiplicative(base,base);
        m>>=1;
    }
    return res;
}


ll fast_pow(ll a,ll n,ll mod)
{
    ll ans = 1;
    while(n)
    {
        if(n&1) ans = ans * a % mod;
        a = a*a % mod;
        n >>= 1;
    }
    return ans;
}
ll ans[N];

int looped[46337 + 10];

int getloop(int mod)
{
    if(looped[mod]) return looped[mod];
    ans[0] = 2%mod;ans[1] = 10%mod;
    for(int i = 2;;i++)
    {
        ans[i] = (ans[i - 1]*10ll%mod - ans[i - 2] + mod)%mod;
     //   cout<<i<<endl;
        if(ans[i-1] == ans[0] && ans[i] == ans[1])    return looped[mod] = i - 1;

    }

}


int main()
{
    int t,kase = 0,x;
    memset(looped,0,sizeof(looped));
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&x,&MOD);
        int loop = getloop(MOD);
        //cout<<loop<<endl;
        int n = (fast_pow(2,x,loop) + 1 ) % loop;
        ll a = 5;
        ll b = 24;
        //cout<<n<<endl;
        if(n == 0)  printf("Case #%d: %lld\n",++kase,1%MOD);
        else if(n == 1)  printf("Case #%d: %lld\n",++kase,(2*a-1)%MOD);
        else{
            Matrix base={
                2*a,-(a*a-b),
                1,0
            };
            base=pow(base,n-1);
            printf("Case #%d: %lld\n",++kase,(2*a%MOD*base.matrix[0][0]%MOD+2*base.matrix[0][1]%MOD+MOD - 1)%MOD);
        }
    }
}

 

posted @ 2018-10-02 09:30  jadelemon  阅读(124)  评论(0编辑  收藏  举报