• HDU 4471 矩阵快速幂 Homework


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4471

    解题思路,矩阵快速幂····特殊点特殊处理·····

    令h为计算某个数最多须知前h个数,于是写出方程:

    D =

    c1 c2 ``` c[h-1] c[h]
    1 0 ``` 0 0
    0 1 ``` 0 0
    0 0   0 0
    0 0   1 0

    V[x] =

    f[x]
    f[x-1]
    `
    `
    f[x-h+1]

    显然有V[x+1] = D*V[x].D是由系数行向量,一个(h-1)*(h-1)的单位矩阵,和一个(h-1)*1的0矩阵组成。V[x]是一个h行,1列的矩阵。

    初始条件为V[m] = (f[m],f[m-1],`````).如果m>h,那么多余的部分不会用到,如果m<h剩下的部分用0取代,相当于人为的添加前项f[0] = 0,f[-1] = 0·····这不会影响结果,而且式子仍然成立。由此计算出V[n],答案就为V[1][1].

    其余看一下代码就OK了,还有别人的解题报告,也可以看一下:

    链接:

    http://www.07net01.com/program/547544.html

    我的代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N =102;
     5 const int mod = 1000000007;
     6 int h;//计算f[x]时最多和前面h个数有关
     7 struct matrix
     8 {
     9     int row,col;
    10     int m[N][N];
    11     void init(int row,int col)
    12     {
    13         this->row = row;
    14         this->col = col;
    15         for(int i=0; i<=row; ++i)
    16             for(int j=0; j<=col; ++j)
    17                 m[i][j] = 0;
    18     }
    19 } A,pm[33],ans;
    20 
    21 matrix operator*(const matrix & a,const matrix& b)
    22 {
    23     matrix res;
    24     res.init(a.row,b.col);
    25     for(int k=1; k<=a.col; ++k)
    26     {
    27         for(int i=1; i<= res.row; ++i)
    28         {
    29             if(a.m[i][k] == 0 ) continue;
    30             for(int j = 1; j<=res.col; ++j)
    31             {
    32                 if(b.m[k][j] == 0 ) continue;
    33                 res.m[i][j] = (1LL *a.m[i][k]*b.m[k][j] + res.m[i][j])%mod;
    34             }
    35         }
    36     }
    37     return res;
    38 }
    39 
    40 void cal(int x)
    41 {
    42     for(int i=0; i<=31; ++i)
    43         if(x & (1<<i) ) ans = pm[i]*ans;
    44 }
    45 void getPm()
    46 {
    47     pm[0] = A;
    48     for(int i=1; i<=31; ++i)
    49         pm[i] = pm[i-1]*pm[i-1];
    50 }
    51 struct sp//特殊点
    52 {
    53     int nk,tk;//nk为点的位置,tk为计算nk时和前面tk个数有关
    54     int ck[N];
    55     bool operator<(const sp & o)const//按照nk排序
    56     {
    57         return nk<o.nk;
    58     }
    59 } p[N];
    60 int main()
    61 {
    62 //    freopen("in.txt","r",stdin);
    63     int n,m,q,t,f[N],c[N],kase=0;
    64     while(~scanf("%d%d%d",&n,&m,&q))
    65     {
    66         for(int i=m; i>0; --i)   scanf("%d",&f[i]);
    67         scanf("%d",&t);
    68         h =t;
    69         for(int i=1; i<=t; ++i)  scanf("%d",&c[i]);
    70         for(int i=0; i<q; ++i)
    71         {
    72             scanf("%d%d",&p[i].nk,&p[i].tk);
    73             if(p[i].tk > h) h = p[i].tk;
    74             for(int j=1; j<=p[i].tk; ++j) scanf("%d",&p[i].ck[j]);
    75         }
    76         sort(p,p+q);
    77         A.init(h,h);
    78         for(int i=1; i<=t; ++i) A.m[1][i] = c[i];
    79         for(int i=2; i<=h; ++i)  A.m[i][i-1] = 1;
    80         getPm();
    81         ans.init(h,1);
    82         for(int i = m; i > 0; --i)   ans.m[i][1] = f[i];
    83         int last=m;
    84         for(int i=0; i<q; ++i)
    85         {
    86             if( p[i].nk <=last ||  p[i].nk >n ) continue;
    87             cal( p[i].nk-last-1);
    88             last =  p[i].nk;
    89             for(int j=1; j<=p[i].tk; ++j)  A.m[1][j] = p[i].ck[j];
    90             for(int j=p[i].tk+1; j<=h; ++j) A.m[1][j] = 0;
    91             ans  =A*ans;
    92         }
    93         cal(n-last);
    94         printf("Case %d: %d
    ",++kase,ans.m[1][1]);
    95     }
    96     return 0;
    97 }
    View Code
  • 相关阅读:
    v-chart使用的相关实例
    v-chart从后台获取数据
    算法题-单词搜索
    关于前端开发的一些小经验总结
    element的input中加入可点击的按钮
    vue.js的入门
    链表问题(算法题)
    同构词分类
    最长不降序子列的改编(dp数组的使用)
    Ubuntu安装Git
  • 原文地址:https://www.cnblogs.com/allh123/p/3296276.html
Copyright © 2020-2023  润新知