zoukankan      html  css  js  c++  java
  • HDU 1757 A Simple Math Problem(矩阵高速幂)

    题目地址:HDU 1757

    最终会构造矩阵了。事实上也不难,仅仅怪自己笨。。= =! 

    f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10)
    构造的矩阵是:(我代码中构造的矩阵跟这个正好是上下颠倒过来了)
    |0 1 0 ......... 0|    |f0|   |f1 |
    |0 0 1 0 ...... 0|    |f1|   |f2 |
    |...................1| *  |..| = |...|
    |a9 a8 .......a0|    |f9|   |f10|

    然后依据矩阵的结合律,能够先把构造的矩阵的(k-9)次幂求出来。最后直接求第一个数。

    代码例如以下:

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <stdlib.h>
    #include <math.h>
    #include <ctype.h>
    #include <queue>
    #include <map>
    #include <set>
    #include <algorithm>
    
    using namespace std;
    int mod, a[20];
    struct matrix
    {
        int ma[20][20];
    } init, res, s;
    matrix Mult(matrix x, matrix y)
    {
        int i, j, k;
        matrix tmp;
        for(i=0; i<10; i++)
        {
            for(j=0; j<10; j++)
            {
                tmp.ma[i][j]=0;
                for(k=0; k<10; k++)
                {
                    tmp.ma[i][j]=(tmp.ma[i][j]+x.ma[i][k]*y.ma[k][j])%mod;
                }
            }
        }
        return tmp;
    }
    matrix Pow(matrix x, int k)
    {
        matrix tmp;
        int i, j;
        for(i=0; i<10; i++) for(j=0; j<10; j++) tmp.ma[i][j]=(i==j);
        while(k)
        {
            if(k&1) tmp=Mult(tmp,x);
            x=Mult(x,x);
            k>>=1;
        }
        return tmp;
    }
    int main()
    {
        int k, x, i, j;
        while(scanf("%d%d",&k,&mod)!=EOF)
        {
            if(k<10)
            {
                printf("%d
    ",k%mod);
                continue ;
            }
            for(i=9; i>=0; i--)
            {
                a[i]=9-i;
            }
            for(i=0; i<10; i++)
            {
                scanf("%d",&x);
                init.ma[0][i]=x%mod;
            }
            for(i=1; i<10; i++)
            {
                for(j=0; j<10; j++)
                {
                    init.ma[i][j]=(i==j+1);
                }
            }
            res=Pow(init,k-9);
            /*for(i=0; i<10; i++)
            {
                for(j=0; j<10; j++)
                {
                    printf("%d ",res.ma[i][j]);
                }
                puts("");
            }*/
            int ans=0;
            for(j=0; j<10; j++)
            {
                ans=(ans+res.ma[0][j]*a[j])%mod;
                //printf("%d %d %d
    ",res.ma[i][j],a[i],ans);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    


  • 相关阅读:
    [题解?]luogu_P1415拆分数列(dp(不懂
    [题解]luogu_P1070道路游戏(堆dp
    [题解]luogu_P2577午餐(贪心dp
    [题解]luogu_P2157学校食堂(状压dp
    [模板]线段树合并
    [题解]宝藏(状压
    [题解]NOI2010超级钢琴
    [题解]luogu_P2161_会场预约(线段树颜色相关
    【总结】LCA的4种求法
    SRM517-600加强版(DP)
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4040620.html
Copyright © 2011-2022 走看看