其他分享
首页 > 其他分享> > [HNOI 2011] 数学作业

[HNOI 2011] 数学作业

作者:互联网

[题目链接]

          https://www.lydsy.com/JudgeOnline/problem.php?id=2326

[算法]

        .矩阵乘法即可

         时间复杂度 : O(logN)

[代码]

          

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

ll n;
int m;
int mat[4][4];
ll pw[20];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
inline int len(ll x)
{
        int ret = 0;
        while (x > 0) ++ret , x /= 10;
        return ret;
}
inline void multipy(int a[4][4] , int b[4][4])
{
        int ret[4][4];
        memset(ret , 0 , sizeof(ret));
        for (int i = 1; i <= 3; i++)
        {
                for (int j = 1; j <= 3; j++)
                {
                        for (int k = 1; k <= 3; k++)
                        {
                                ret[i][j] = (ret[i][j] + 1ll * a[i][k] % m * b[k][j] % m) % m;
                        }
                }
        }
        for (int i = 1; i <= 3; i++)
        {
                for (int j = 1; j <= 3; j++)
                {
                        a[i][j] = ret[i][j];
                }
        }
}
inline void exp_mod(int base[4][4] , ll n)
{
        int ret[4][4];
        for (int i = 1; i <= 3; i++)
        {
                for (int j = 1; j <= 3; j++)
                {
                        ret[i][j] = (i == j); 
                }
        }
        while (n > 0)
        {
                if (n & 1) multipy(ret , base);
                multipy(base , base);
                n >>= 1;
        }
        for (int i = 1; i <= 3; i++)
        {
                for (int j = 1; j <= 3; j++)
                {
                        base[i][j] = ret[i][j];
                }
        }
}

int main()
{
        
        read(n); read(m);
        int L = len(n);
        pw[0] = 1;
        for (int i = 1; i <= L; i++) pw[i] = pw[i - 1] * 10;
        int ans = 0;
        for (int i = 1; i < L; i++)
        {
                mat[1][1] = (1ll * pw[i] % m); mat[1][2] = 1; mat[1][3] = 0;
                mat[2][1] = 0; mat[2][2] = 1; mat[2][3] = 1;
                mat[3][1] = 0; mat[3][2] = 0; mat[3][3] = 1;
                exp_mod(mat , pw[i] - pw[i - 1]);        
                ans = (1ll * mat[1][1] % m * ans % m + 1ll * mat[1][2] % m * (pw[i - 1] % m) + mat[1][3] % m) % m;
        }
        mat[1][1] = pw[L] % m; mat[1][2] = 1; mat[1][3] = 0;
        mat[2][1] = 0; mat[2][2] = 1; mat[2][3] = 1;
        mat[3][1] = 0; mat[3][2] = 0; mat[3][3] = 1;
        exp_mod(mat , n - pw[L - 1] + 1);
        ans = (1ll * mat[1][1] * ans % m + 1ll * mat[1][2] * (pw[L - 1] % m) + mat[1][3] % m) % m;
        printf("%d\n" , ans);
        
        return 0;
    
}

 

标签:int,HNOI,作业,long,ret,template,inline,2011,void
来源: https://www.cnblogs.com/evenbao/p/10459655.html