• 「模拟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
    ",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
    ",ans[0]%mod);
    95      else printf("%lld
    ",fir[0]%mod);
    96 }
    View Code
  • 相关阅读:
    TCP/IP四层模型
    Java编程题
    大整数阶乘的运算(可以计算1000!) .
    sleep和wait的区别
    Javascript保留字(Javascript Reserved Words)
    WEBLOGIC 内存溢出 解决方案
    Java学习的30个目标以及系统架构师推荐的书
    笔记分析
    MySQL分区(Partition)功能试验
    Java线程:生产者消费者模型
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11421020.html
Copyright © 2020-2023  润新知