zoukankan      html  css  js  c++  java
  • 【题解】HDU Homework(倍增)

    【题解】HDU Homework(倍增)

    矩阵题一定要多多检查一下是否行列反了...

    一百个递推项一定要存101个

    说多了都是泪啊

    一下午就做了这一道题因为实在是太菜了太久没写这种矩阵的题目...

    设一个行向量(e),和一个增逛矩阵(A),他们咋定义的见我那篇讲线性递推博客

    现在我们再预处理(st)矩阵数组,其中(st_i=A^{2^i})

    考虑这样一种做法,我们考虑让(e)总共有101个值,然后当第一个值被增逛为(f_{q.n-100})时,暴力将(e)中的第(101)项修改。中间的转移直接利用这个倍增数组。中间的转移由于是倍增,而且是行乘以一个矩阵,这样的话复杂度就是(O(m^2))。考虑一个询问就要处理一次最终复杂度(O(m^3log n+qm^2log n))

    细节要处理一下

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    
    using namespace std;  typedef long long ll;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    const int maxn=1e2+3;
    const int mod=1e9+7;
    int n,m,q,T;
    const int M=101;
    struct MAT{
          int data[maxn][maxn];
          MAT(){memset(data,0,sizeof data);}
          inline int*operator [](int x){return data[x];}
          inline MAT operator *(MAT&f){
    	    MAT ret;
    	    for(int k=1;k<=M;++k)
    		  for(int t=1;t<=M;++t)
    			for(int i=1;i<=M;++i)
    			      ret[t][i]=(ret[t][i]+1ll*data[t][k]*f[k][i])%mod;
    	    return ret;
          }
    }st[31];
    
    struct line{
          int data[maxn];
          line(){memset(data,0,sizeof data);}
          inline int&operator[](int x){return data[x];}
          inline line operator *(MAT&f){
    	    line ret;
    	    for(int i=1;i<=M;++i)
    		  for(int t=1;t<=M;++t)
    			ret[t]=(ret[t]+1ll*data[i]*f[i][t])%mod;
    	    return ret;
          }
    }e;
    
    int init[maxn];
    pair<pair<int,int>,vector<int> > Q[maxn];
    
    inline void pow(const int&num){
          for(int t=0;t<30;++t)
    	    if(num>>t&1)
    		  e=e*st[t];
    }
    
    int main(){
          int cnt=0;
          while(~scanf("%d%d%d",&n,&m,&q)){
    	    memset(st[0].data,0,sizeof st[0].data);
    	    memset(e.data,0,sizeof e.data);
    	    for(int t=1;t<=m;++t) e[t]=init[t]=qr()%mod;
    	    for(int t=1;t<M;++t) st[0][t+1][t]=1;
    	    T=qr();
    	    for(int t=1;t<=T;++t) st[0][M-t+1][M]=qr()%mod;
    	    for(int t=1;t<30;++t) st[t]=st[t-1]*st[t-1];
    	    for(int t=1;t<=q;++t){
    		  Q[t].first.first=qr();
    		  Q[t].first.second=qr();
    		  Q[t].second.clear();
    		  Q[t].second.push_back(0);
    		  for(int i=1;i<=Q[t].first.second;++i) Q[t].second.push_back(qr());
    	    }
    	    sort(Q+1,Q+q+1);
    	    int l=1;
    	    for(int t=m+1;t<=M;++t){
    		  if(t==Q[l].first.first&&l<=q){
    			int ret=0;
    			for(int i=1;i<=Q[l].first.second;++i)
    			      ret=(ret+1ll*init[t-i]*Q[l].second[i])%mod;
    			init[t]=ret;
    			++l;
    		  }
    		  else {
    			int ret=0;
    			for(int i=1;i<=T;++i)
    			      ret=(ret+1ll*init[t-i]*st[0][M-i+1][M])%mod;
    			init[t]=ret;
    		  }
    	    }
    	    for(int t=1;t<=M;++t) e[t]=init[t];
    	    if(n<=M) {printf("Case %d: %d
    ",++cnt,init[n]); continue;}
    	    int cur=1;
    	    for(;l<=q;++l){
    		  if(Q[l].first.first>n) break;
    		  pow(Q[l].first.first-(cur+M-1));
    		  cur+=Q[l].first.first-(cur+M-1);
    		  e[M]=0;
    		  for(int t=1;t<=Q[l].first.second;++t)
    			e[M]=(e[M]+1ll*Q[l].second[t]*e[M-t])%mod;
    	    }
    	    pow(n-cur);
    	    printf("Case %d: %d
    ",++cnt,e[1]);
          }
          return 0;
    }
    
    
  • 相关阅读:
    HDU4628+状态压缩DP
    Javascript 去掉字符串前后空格的五种方法
    Javascript 数组之判断取值和数组取值
    ASP.NET MVC 出现错误 “The view 'XXX' or its master was not found or no view engine support”
    ASP.NET MVC 页面调整并传递参数
    ASP.NET MV3 部署网站 报"Could not load file or assembly ' System.Web.Helpers “ 错的解决方法
    ASP.NET MVC 控制器向View传值的三种方法
    CSharp 如何通过拼接XML调用存储过程来查询数据
    SQLServer : EXEC和sp_executesql的区别
    关于SQLServer2005的学习笔记—异常捕获及处理
  • 原文地址:https://www.cnblogs.com/winlere/p/11559912.html
Copyright © 2011-2022 走看看