zoukankan      html  css  js  c++  java
  • HDU 1757 矩阵相乘,快速幂模板题

    HDU 1757

    题意:  If x < 10, f(x) = x;  

         If x >= 10, f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10); 

          给出k和mod,求f(k)。

    总结 1、特别注意,矩阵相乘不满足交换律,即a*b != b*a。  2、感觉推方程有点困难。 3、矩阵初始化注意。


    f(x-10)   0 0 0 0 0 0 0 0 0        ( first矩阵 )      
    f(x-9)     0 0 0 0 0 0 0 0 0
    f(x-8)     0 0 0 0 0 0 0 0 0
    f(x-7)     0 0 0 0 0 0 0 0 0
    f(x-6)     0 0 0 0 0 0 0 0 0
    f(x-5)     0 0 0 0 0 0 0 0 0
    f(x-4)     0 0 0 0 0 0 0 0 0
    f(x-3)     0 0 0 0 0 0 0 0 0
    f(x-2)     0 0 0 0 0 0 0 0 0
    f(x-1)     0 0 0 0 0 0 0 0 0

    *

      0 1 0 0 0 0 0 0 0 0      ( temp矩阵 )
      0 0 1 0 0 0 0 0 0 0
      0 0 0 1 0 0 0 0 0 0
      0 0 0 0 1 0 0 0 0 0
      0 0 0 0 0 1 0 0 0 0
      0 0 0 0 0 0 1 0 0 0
      0 0 0 0 0 0 0 1 0 0
      0 0 0 0 0 0 0 0 1 0
      0 0 0 0 0 0 0 0 0 1

    a9 8 7 6 5 4 3 2 1 0  (这一行是ai)

    =
                
    f(x-9)     0 0 0 0 0 0 0 0 0
    f(x-8)     0 0 0 0 0 0 0 0 0
    f(x-7)     0 0 0 0 0 0 0 0 0
    f(x-6)     0 0 0 0 0 0 0 0 0
    f(x-5)     0 0 0 0 0 0 0 0 0
    f(x-4)     0 0 0 0 0 0 0 0 0
    f(x-3)     0 0 0 0 0 0 0 0 0
    f(x-2)     0 0 0 0 0 0 0 0 0
    f(x-1)     0 0 0 0 0 0 0 0 0
    f(x)        0 0 0 0 0 0 0 0 0   

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<bitset>
    #include<vector>
    #include<set>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define F(i,a,b)  for (int i=a;i<b;i++)
    #define FF(i,a,b) for (int i=a;i<=b;i++)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    typedef long long ll;
    const int N = 1e5+10, Maxn = 15;
    
    ll k,m=100;
    struct Mat
    {
        ll mat[Maxn][Maxn];
        Mat() {
            mes(mat,0);
            F(i,0,Maxn) mat[i][i]=1;
        }
    } E;
    Mat first, temp;
    
    Mat operator * (Mat a, Mat b)
    {
        Mat ans;
        memset(ans.mat, 0, sizeof(ans.mat));
        for (int i = 0; i < Maxn; i++)
            for (int j = 0; j < Maxn; j++)
                for (int k = 0; k < Maxn; k++)
                    ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % m;
        return ans;
    }
    Mat operator ^ (Mat a,ll x)
    {
        Mat p = E, q = a;
        while (x) {
            if(x&1)  p = p*q;
            x>>=1;
            q = q*q;
        }
        return p;
    }
    int main()
    {
        mes(first.mat, 0);
        F(i,0,10) first.mat[i][0]=i;
        while(~scanf("%lld%lld", &k, &m)) {
            mes(temp.mat, 0);
            FF(i,0,8) temp.mat[i][i+1]=1;
            F(i,0,10) {
                scanf("%lld", &temp.mat[9][9-i]);
            }
            if(k<10) {
                printf("%lld
    ", k);
                continue;
            }
            Mat ans= (temp^(k-9))*first;   //注意,这里顺序不要反了
            printf("%lld
    ", ans.mat[9][0]);
        }
    
        return 0;
    }
    View Code

    矩阵模板

    const ll mod = 10, N = 31;
    struct Mat
    {
        ll mat[N][N];
        Mat() {
            mes(mat,0);
            for(int i=0; i<N; ++i) mat[i][i]=1;  //对角线初始化为1,其它为0
        }
    } E;  //单位矩阵
    Mat Zero;  //  Zero 要清 0
    ll  len = n;
    Mat operator * (Mat a, Mat b)  //重载 * ,特别注意,矩阵相乘不满足交换律,即a*b != b*a
    {
        Mat ans;
        memset(ans.mat, 0, sizeof(ans.mat));
        for (ll i = 0; i < len; i++)
            for (ll j = 0; j < len; j++)
                for (ll k = 0; k < len; k++)
                    ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][k] * b.mat[k][j]%10) % mod;
        return ans;
    }
    Mat operator ^ (Mat a, ll x)  //重载 ^
    {
        Mat p = E, q = a;
        while (x) {
            if(x&1)  p = p*q;
            x >>= 1;
            q = q*q;
        }
        return p;
    }
    Mat mul(Mat a,Mat b)    //函数 *
    {
        Mat ans;
        for(int i=0; i<len; i++)
            for(int j=0; j<len; j++)
            {
                ans.mat[i][j]=0;
                for(int k=0; k<len; k++)
                    ( ans.mat[i][j] += a.mat[i][k]*b.mat[k][j]%mod ) %= mod;
            }
        return ans;
    }
    Mat Pow_mod(Mat s, int b){   //函数开方
        Mat ans;
        for(int i=0; i<len; ++i) ans.mat[i][i]=1;
        while(b) {
            if(b&1) ans = mul(ans, s);
            s= mul(s, s);
            b >>= 1;
        }
        return ans;
    }
    void prMat(Mat a)
    {
        for(ll i=0; i<len; i++)
            for(ll j=0; j<len; j++)
                printf("%lld%c", a.mat[i][j], " 
    "[j==len-1]);
    }
    Mat Add(Mat a, Mat b)
    {
        Mat s;
        for(int i=0; i<len; ++i)
            for(int j=0; j<len; ++j)
                s.mat[i][j] = (a.mat[i][j] + b.mat[i][j]) % mod;
        return s;
    }
  • 相关阅读:
    hdu-1142(记忆化搜索+dij)
    hdu-1140(求距离,精度判断)
    hdu-1131(卡特兰数+大数)
    hdu-1130(卡特兰数+大数乘法,除法模板)
    hdu-1129(模拟题)
    hdu-1128(数学问题,筛数)
    hdu-1124(数学问题,求n!的尾零的个数)
    hdu-1115(计算多边形重心)
    hdu-1121(差分法--数学问题)
    表达式求值(堆栈)
  • 原文地址:https://www.cnblogs.com/sbfhy/p/6295386.html
Copyright © 2011-2022 走看看