「模拟8.21」山洞(矩阵优化DP)

Posted wwb123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「模拟8.21」山洞(矩阵优化DP)相关的知识,希望对你有一定的参考价值。

暴力:

 

正解:

考虑循环矩阵,f[i][j]表示从i点到j点的方案数

我们发现n很小,我们预处理出n次的f[i][j]

然后在矩阵快速幂中,我们要从当前的f[i][j]*f[j][k]-->fir[i][j]

但是此时的循环为三层

我们考虑转移式子的意义在0-n次从i-j,在n+1到2×n转移至j

这样此时的j-k其实可以把他看作从0开始走j-k步本质上是一样的

然后还有一个特判,就不讲了

         for(int j=0;j<n;++j)
                      
             ff[now][j]=(ff[now][j]+ff[last][((j-i)+n)%n])%mod;
             if((((j-i)+n)%n)==(j+i)%n)continue;
             ff[now][j]=(ff[now][j]+ff[last][(j+i)%n])%mod;    
         

 

代码

技术图片
 1 #include<bits/stdc++.h>
 2 #define int long long
 3 #define MAXN 4001
 4 using namespace std;
 5 int c[MAXN],f[MAXN],fir[MAXN];
 6 int n,m;
 7 const int mod=1e9+7;
 8 void cheng(int k)
 9 
10      memset(c,0,sizeof(c));
11      if(k==1)
12      
13         for(int i=0;i<n;++i)
14         
15             for(int j=0;j<n;++j)
16             
17                c[(i+j)%n]=(c[(i+j)%n]+f[j]*f[i]+mod)%mod;            
18                //if(i*2==(j+i)%n)continue;
19             
20         
21         for(int i=0;i<n;++i)f[i]=c[i]%mod;
22          
23      else
24      
25         for(int i=0;i<n;++i)
26         
27             for(int j=0;j<n;++j)
28             
29                 c[(i+j)%n]=(c[(i+j)%n]+fir[j]*f[i]+mod)%mod;                
30                 //if(i*2==((j+i)%n))continue;
31             
32         
33         for(int i=0;i<n;++i)fir[i]=c[i]%mod;
34      
35 
36 void poww(int y)
37 
38      fir[0]=1ll;
39      while(y)
40      
41          if(y&1ll)cheng(2ll);
42          cheng(1ll);
43          y>>=1ll;
44      
45 
46 int ff[4ll][MAXN];int g[MAXN];
47 int now,last;int ans[MAXN];
48 signed main()
49 
50      //freopen("text.in","r",stdin);
51      //freopen("1.out","w",stdout);
52      scanf("%lld%lld",&n,&m);
53      int now=1;int last=0;
54      ff[0][0]=1;
55      for(int i=1;i<=n;++i)
56      
57          if(i>1)
58          
59              swap(now,last);memset(ff[now],0,sizeof(ff[now]));
60          
61          for(int j=0;j<n;++j)
62                       
63              ff[now][j]=(ff[now][j]+ff[last][((j-i)+n)%n])%mod;
64              if((((j-i)+n)%n)==(j+i)%n)continue;
65              ff[now][j]=(ff[now][j]+ff[last][(j+i)%n])%mod;    
66          
67          if(i==m%n)
68          
69             for(int j=0;j<n;++j)
70             
71                g[j]=ff[now][j]%mod;
72             
73          
74          if(i==m)
75          
76             printf("%lld\n",ff[now][0]);
77             return 0;
78          
79      
80      for(int i=0;i<n;++i)
81      
82         f[i]=ff[now][i]%mod;
83      
84      poww(m/n);
85      for(int i=0;i<n;++i)
86      
87          for(int j=0;j<n;++j)
88          
89              //if(i*2==((j+i)%n))continue;
90              ans[(i+j)%n]=(ans[(i+j)%n]+(g[i]*fir[j])%mod+mod)%mod;
91          
92      
93      if(m%n)
94      printf("%lld\n",ans[0]%mod);
95      else printf("%lld\n",fir[0]%mod);
96 
View Code

 

以上是关于「模拟8.21」山洞(矩阵优化DP)的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder abc256全题解(区间合并模板矩阵快速幂优化dp线段树……)

矩阵乘法优化dp

HDU 5607 graph(矩阵优化+概率DP)

DP优化:矩阵乘法

CodeForces621E 快速矩阵幂优化dp

矩阵快速幂 优化dp 模板