zoukankan      html  css  js  c++  java
  • zoj3256

    好题,由m的范围知道这肯定是矩阵乘法加速插头dp,关键是怎么写

    以往插头dp常用逐格递推,而这道题要求整行逐列递推

    这样我们才能构造转移矩阵。

    我们可以通过假象一个第0列来将路径转化为回路问题

    逐列递推依然使用最小表示法,维护这一列每个格子向右的插头的连通性(最小表示法)

    我们可以通过已知状态不断扩展出新的状态(初始显然只有无右插头和顶部底部有右插头两种情况)

    对于一个已知列插头状态,我们穷举下一列每一个格子是否有插头,就知道了下一列每个格子是否有左插头和右插头

    由于一个格子有且仅有两个插头,因此我们就确定了这一列的情况从而可以不断的扩展出新的合法状态

    而最终合法状态不会超过150,接下来矩阵快速幂即可

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 
      6 using namespace std;
      7 typedef long long ll;
      8 const int mo=7777777;
      9 const int has=419;
     10 int b[15],v[15],n,m,t;
     11 struct node
     12 {
     13     int len,st[1010],p[has],nex[1010];
     14     void clr()
     15     {
     16         len=0;
     17         memset(p,255,sizeof(p));
     18     }
     19     int push(int nw)
     20     {
     21         int x=nw%has;
     22         for (int i=p[x]; i>-1; i=nex[i])
     23             if (st[i]==nw) return i;
     24         st[++len]=nw;
     25         nex[len]=p[x]; p[x]=len;
     26         return len;
     27     }
     28 } f;
     29 
     30 struct mat{
     31     int a[150][150];
     32     friend mat operator *(mat a,mat b)
     33     {
     34         mat c;
     35         for (int i=1; i<=t; i++)
     36             for (int j=1; j<=t; j++)
     37             {
     38                 ll s=0;
     39                 for (int k=1; k<=t; k++) s+=(ll)a.a[i][k]*b.a[k][j];
     40                 c.a[i][j]=s%mo;
     41             }
     42         return c;
     43     }
     44 } ans,c;
     45 
     46 void get(int st)
     47 {
     48     for (int i=n-1; i>=0; i--)
     49     {
     50         b[i]=st&3;
     51         st>>=2;
     52     }
     53 }
     54 
     55 int put()
     56 {
     57     memset(v,255,sizeof(v)); v[0]=0;
     58     int t=0,st=0;
     59     for (int i=0; i<n; i++)
     60     {
     61         if (v[b[i]]==-1) v[b[i]]=++t;
     62         st<<=2;
     63         st|=v[b[i]];
     64     }
     65     return st;
     66 }
     67 
     68 bool check(int cur,int nw)
     69 {
     70     get(cur);
     71     int pre=0,k=0,t=n;
     72     for (int i=0; i<n; i++)
     73     {
     74         int x=(nw>>i)&1;
     75         if (pre==0)
     76         {
     77             if (!b[i]&&!x) return 0;
     78             if (b[i]&&x) continue;
     79             if (b[i]) {pre=b[i];b[i]=0;}
     80             else pre=-1;
     81             k=i;
     82         }
     83         else {
     84             if (b[i]&&x) return 0;
     85             if (!b[i]&&!x) continue;
     86             if (b[i])
     87             {
     88                 if (b[i]==pre&&(nw!=0||i!=n-1)) return 0;
     89                 if (pre>0)
     90                 {
     91                     for (int r=0; r<n; r++)
     92                         if (i!=r&&b[r]==b[i]) b[r]=pre;
     93                     b[i]=0;
     94                 }
     95                 else {b[k]=b[i],b[i]=0;}
     96             }
     97             else {
     98                 if (pre>0) b[i]=pre;
     99                 else b[i]=b[k]=++t;
    100             }
    101             pre=0;
    102         }
    103     }
    104     return pre==0;
    105 }
    106 
    107 void quick(int n)
    108 {
    109     memset(ans.a,0,sizeof(ans.a));
    110     for (int i=1; i<=t; i++) ans.a[i][i]=1;
    111     while (n)
    112     {
    113         if (n&1) ans=ans*c;
    114         c=c*c;
    115         n>>=1;
    116     }
    117 }
    118 
    119 int main()
    120 {
    121     while (scanf("%d%d",&n,&m)!=EOF)
    122     {
    123         memset(b,0,sizeof(b));
    124         memset(c.a,0,sizeof(c.a));
    125         f.clr();
    126         f.push(0);
    127         b[0]=b[n-1]=1; f.push(put());
    128         for (int i=2; i<=f.len; i++)
    129             for (int j=0; j<(1<<n); j++)
    130                 if (check(f.st[i],j))
    131                 {
    132                     int k=f.push(put());
    133                     c.a[i][k]=1;
    134                 }
    135         t=f.len;
    136         quick(m);
    137         if (ans.a[2][1]==0) puts("Impossible");
    138         else printf("%d
    ",ans.a[2][1]);
    139     }
    140 }
    View Code
  • 相关阅读:
    请求返回结果模板
    Oracle的sql语句中case关键字的用法 & 单双引号的使用
    java如何从方法返回多个值
    junit的简单用法
    java命令启动jar包
    Fastjson-fastjson中$ref对象重复引用问题
    指定cmd窗口或tomcat运行窗口的名称
    Spring boot配置log4j输出日志
    The import XXX cannot be resolved
    斐波那契数列
  • 原文地址:https://www.cnblogs.com/phile/p/6354580.html
Copyright © 2011-2022 走看看