2#includ" />

欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

BZOJ 1494 [NOI2007]生成樹計數 矩陣乘法+DP

系統 1906 0

題解:

這種數據范圍果斷矩陣乘法,其實dp什么的也特別顯然,就是求轉移矩陣特別惡心。

最小表示法(表示現學的壓力比較大) 表示連通性。

能多暴力就多暴力的枚舉,反正數據范圍小~

唯一需要注意的是轉移的時候有兩種情況是不合法的:

1、第(i-k)個點不和第(i-k+1)到i個點連通

2、第i個點連到已經在一個連通塊中的兩個點

?

wa了半天,然后不想做了的時候突然發現ac了。。莫名其妙。。。

?

代碼比較丑陋。。

View Code
        
            1
        
         #include <iostream>


        
            2
        
         #include <cstdlib>


        
            3
        
         #include <cstdio>


        
            4
        
         #include <cstring>


        
            5
        
         #include <algorithm>


        
            6
        
        
            7
        
        
          #define
        
         N 10


        
            8
        
        
          #define
        
         SIZE 60


        
            9
        
        
          #define
        
         mod 65521


        
           10
        
        
           11
        
        
          using
        
        
          namespace
        
        
           std;


        
        
           12
        
        
           13
        
        
          struct
        
        
           MT


        
        
           14
        
        
          {


        
        
           15
        
        
          int
        
        
           x,y;


        
        
           16
        
        
          long
        
        
          long
        
        
           mt[SIZE][SIZE];


        
        
           17
        
        
          }ans,zy;


        
        
           18
        
        
           19
        
        
          int
        
         hash[
        
          100010
        
        ],antihash[
        
          100010
        
        
          ];


        
        
           20
        
        
          int
        
        
           m,fa[N],col[N],cnt;


        
        
           21
        
        
          long
        
        
          long
        
        
           n;


        
        
           22
        
        
          bool
        
        
           map[N][N],vis[N][N];


        
        
           23
        
        
           24
        
         inline MT 
        
          operator
        
         *
        
          (MT a,MT b)


        
        
           25
        
        
          {


        
        
           26
        
             MT c; memset(c.mt,
        
          0
        
        ,
        
          sizeof
        
        
           c.mt);


        
        
           27
        
             c.x=a.x; c.y=
        
          b.y;


        
        
           28
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=c.x;i++
        
          )


        
        
           29
        
        
          for
        
        (
        
          int
        
         j=
        
          1
        
        ;j<=c.y;j++
        
          )


        
        
           30
        
        
          for
        
        (
        
          int
        
         k=
        
          1
        
        ;k<=a.y;k++
        
          )


        
        
           31
        
                         c.mt[i][j]=(c.mt[i][j]+a.mt[i][k]*b.mt[k][j])%
        
          mod;


        
        
           32
        
        
          return
        
        
           c;


        
        
           33
        
        
          }


        
        
           34
        
        
           35
        
         inline 
        
          int
        
         findfa(
        
          int
        
        
           x)


        
        
           36
        
        
          {


        
        
           37
        
        
          if
        
        (fa[x]!=x) 
        
          return
        
         fa[x]=
        
          findfa(fa[x]);


        
        
           38
        
        
          return
        
        
           fa[x];


        
        
           39
        
        
          }


        
        
           40
        
        
           41
        
         inline 
        
          void
        
        
           check()


        
        
           42
        
        
          {


        
        
           43
        
             memset(vis,
        
          1
        
        ,
        
          sizeof
        
        
           vis);


        
        
           44
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=m;i++) fa[i]=
        
          i;


        
        
           45
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<m;i++
        
          )


        
        
           46
        
        
          for
        
        (
        
          int
        
         j=
        
          1
        
        ;j+i<=m;j++
        
          )


        
        
           47
        
        
          if
        
        
          (map[i][j])


        
        
           48
        
        
                      {


        
        
           49
        
        
          if
        
        (findfa(i)==findfa(i+j)) 
        
          return
        
        ;
        
          //
        
        
          判環 
        
        
           50
        
        
          else
        
         fa[findfa(i)]=findfa(i+
        
          j);


        
        
           51
        
        
                      }


        
        
           52
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<m;i++
        
          )


        
        
           53
        
        
          for
        
        (
        
          int
        
         j=
        
          1
        
        ;j+i<=m;j++
        
          )


        
        
           54
        
                     vis[i][i+j]=vis[i+j][i]=!
        
          map[i][j];


        
        
           55
        
        
          for
        
        (
        
          int
        
         k=
        
          1
        
        ;k<=m;k++)
        
          //
        
        
          傳遞閉包 
        
        
           56
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=m;i++
        
          )


        
        
           57
        
        
          for
        
        (
        
          int
        
         j=
        
          1
        
        ;j<=m;j++
        
          )


        
        
           58
        
        
                      {


        
        
           59
        
        
          if
        
        (vis[i][j]==
        
          0
        
        ) 
        
          continue
        
        
          ;


        
        
           60
        
        
          if
        
        (vis[i][k]||vis[k][j]) 
        
          continue
        
        
          ;


        
        
           61
        
                         vis[i][j]=
        
          0
        
        
          ;


        
        
           62
        
        
                      }


        
        
           63
        
        
          int
        
         tmp=
        
          0
        
        
          ;


        
        
           64
        
             memset(col,-
        
          1
        
        ,
        
          sizeof
        
        
           col);


        
        
           65
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=m;i++)
        
          //
        
        
          最小表示法 
        
        
           66
        
        
              {


        
        
           67
        
        
          for
        
        (
        
          int
        
         j=
        
          1
        
        ;j<i;j++
        
          )


        
        
           68
        
        
          if
        
        (vis[j][i]==
        
          0
        
        ) {col[i]=col[j];
        
          break
        
        
          ;}


        
        
           69
        
        
          if
        
        (col[i]==-
        
          1
        
        ) col[i]=tmp++
        
          ;


        
        
           70
        
        
              }


        
        
           71
        
             tmp=
        
          0
        
        
          ;


        
        
           72
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=m;i++) tmp=tmp*
        
          10
        
        +
        
          col[i];


        
        
           73
        
        
          if
        
        (hash[tmp]==
        
          0
        
        
          )


        
        
           74
        
        
              {


        
        
           75
        
                 hash[tmp]=++cnt;
        
          //
        
        
          cnt個最小表示法 
        
        
           76
        
                 antihash[cnt]=
        
          tmp;


        
        
           77
        
        
              }


        
        
           78
        
             ans.mt[hash[tmp]][
        
          1
        
        ]++;
        
          //
        
        
          最小表示法代表的方案數 
        
        
           79
        
        
          }


        
        
           80
        
        
           81
        
         inline 
        
          void
        
         dfs(
        
          int
        
         x,
        
          int
        
        
           y)


        
        
           82
        
        
          {


        
        
           83
        
        
          if
        
        (x==m-
        
          1
        
        &&y==
        
          2
        
        
          ) check();


        
        
           84
        
        
          else
        
        
          if
        
        (x+y==m+
        
          1
        
        ) dfs(x+
        
          1
        
        ,
        
          1
        
        
          );


        
        
           85
        
        
          else
        
        
           86
        
        
              {


        
        
           87
        
                 map[x][y]=
        
          1
        
        ; dfs(x,y+
        
          1
        
        
          );


        
        
           88
        
                 map[x][y]=
        
          0
        
        ; dfs(x,y+
        
          1
        
        
          );


        
        
           89
        
        
              }


        
        
           90
        
        
          }


        
        
           91
        
        
           92
        
         inline 
        
          bool
        
        
           uni()


        
        
           93
        
        
          {


        
        
           94
        
        
          for
        
        (
        
          int
        
         i=
        
          2
        
        ;i<=m;i++
        
          )


        
        
           95
        
        
          if
        
        (col[
        
          1
        
        ]==col[i]) 
        
          return
        
        
          0
        
        
          ;


        
        
           96
        
        
          return
        
        
          1
        
        
          ;


        
        
           97
        
        
          }


        
        
           98
        
        
           99
        
         inline 
        
          int
        
         trans(
        
          int
        
        
           zt)


        
        
          100
        
        
          {


        
        
          101
        
             memset(vis,
        
          1
        
        ,
        
          sizeof
        
        
           vis);


        
        
          102
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=m;i++
        
          )


        
        
          103
        
        
          for
        
        (
        
          int
        
         j=i+
        
          1
        
        ;j<=m;j++
        
          )


        
        
          104
        
        
          if
        
        (col[i]==col[j]) vis[i][j]=vis[j][i]=
        
          0
        
        
          ;


        
        
          105
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=m;i++
        
          )


        
        
          106
        
        
          if
        
        (zt&(
        
          1
        
        <<(m-i))) vis[i][m+
        
          1
        
        ]=vis[m+
        
          1
        
        ][i]=
        
          0
        
        
          ;


        
        
          107
        
        
          for
        
        (
        
          int
        
         k=
        
          1
        
        ;k<=m+
        
          1
        
        ;k++)
        
          //
        
        
          傳遞閉包 
        
        
          108
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=m+
        
          1
        
        ;i++
        
          )


        
        
          109
        
        
          for
        
        (
        
          int
        
         j=
        
          1
        
        ;j<=m+
        
          1
        
        ;j++
        
          )


        
        
          110
        
        
                      {


        
        
          111
        
        
          if
        
        (vis[i][j]==
        
          0
        
        ) 
        
          continue
        
        
          ;


        
        
          112
        
        
          if
        
        (vis[i][k]||vis[k][j]) 
        
          continue
        
        
          ;


        
        
          113
        
                         vis[i][j]=
        
          0
        
        
          ;


        
        
          114
        
        
                      }


        
        
          115
        
             memset(col,-
        
          1
        
        ,
        
          sizeof
        
        
           col);


        
        
          116
        
        
          int
        
         tmp=
        
          0
        
        
          ;


        
        
          117
        
        
          for
        
        (
        
          int
        
         i=
        
          2
        
        ;i<=m+
        
          1
        
        ;i++)
        
          //
        
        
          最小表示法 
        
        
          118
        
        
              {


        
        
          119
        
        
          for
        
        (
        
          int
        
         j=
        
          2
        
        ;j<i;j++
        
          )


        
        
          120
        
        
          if
        
        (vis[j][i]==
        
          0
        
        ) {col[i]=col[j];
        
          break
        
        
          ;}


        
        
          121
        
        
          if
        
        (col[i]==-
        
          1
        
        ) col[i]=tmp++
        
          ;


        
        
          122
        
        
              }


        
        
          123
        
             tmp=
        
          0
        
        
          ;


        
        
          124
        
        
          for
        
        (
        
          int
        
         i=
        
          2
        
        ;i<=m+
        
          1
        
        ;i++) tmp=tmp*
        
          10
        
        +
        
          col[i];


        
        
          125
        
        
          return
        
        
           tmp;


        
        
          126
        
        
          }


        
        
          127
        
        
          128
        
         inline 
        
          int
        
         solve(
        
          int
        
         c,
        
          int
        
        
           zt)


        
        
          129
        
        
          {


        
        
          130
        
        
          for
        
        (
        
          int
        
         i=m;i>=
        
          1
        
        ;i--
        
          )


        
        
          131
        
        
              {


        
        
          132
        
                 col[i]=c%
        
          10
        
        
          ;


        
        
          133
        
                 c/=
        
          10
        
        
          ;


        
        
          134
        
        
              }


        
        
          135
        
             col[m+
        
          1
        
        ]=-
        
          1
        
        
          ;


        
        
          136
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=m;i++
        
          )


        
        
          137
        
        
          for
        
        (
        
          int
        
         j=i+
        
          1
        
        ;j<=m;j++
        
          )


        
        
          138
        
        
          if
        
        (col[i]==col[j]&&(zt&(
        
          1
        
        <<(m-i)))&&(zt&(
        
          1
        
        <<(m-j)))) 
        
          return
        
         -
        
          1
        
        ;
        
          //
        
        
        
          139
        
        
          if
        
        (!(zt&(
        
          1
        
        <<(m-
        
          1
        
        )))&&uni()) 
        
          return
        
         -
        
          1
        
        ;
        
          //
        
        
          最左側的點不連通
        
        
          140
        
        
          return
        
        
           trans(zt);


        
        
          141
        
        
          }


        
        
          142
        
        
          143
        
         inline 
        
          void
        
         get_det()
        
          //
        
        
          求出轉移矩陣 
        
        
          144
        
        
          {


        
        
          145
        
             ans.x=cnt; ans.y=
        
          1
        
        
          ;


        
        
          146
        
             zy.x=zy.y=
        
          cnt;


        
        
          147
        
        
          for
        
        (
        
          int
        
         i=
        
          1
        
        ;i<=cnt;i++
        
          )


        
        
          148
        
        
              {


        
        
          149
        
        
          int
        
         lim=
        
          1
        
        <<
        
          m,pa;


        
        
          150
        
        
          for
        
        (
        
          int
        
         j=
        
          0
        
        ;j<lim;j++
        
          )


        
        
          151
        
        
                  {


        
        
          152
        
                     pa=
        
          solve(antihash[i],j);


        
        
          153
        
        
          if
        
        (pa==-
        
          1
        
        ) 
        
          continue
        
        
          ;


        
        
          154
        
                     zy.mt[hash[pa]][i]++
        
          ;


        
        
          155
        
        
                  }


        
        
          156
        
        
              }


        
        
          157
        
        
          }


        
        
          158
        
        
          159
        
         inline 
        
          void
        
        
           go()


        
        
          160
        
        
          {


        
        
          161
        
             scanf(
        
          "
        
        
          %d%lld
        
        
          "
        
        ,&m,&
        
          n);


        
        
          162
        
        
          if
        
        (m==
        
          1
        
        ) {puts(
        
          "
        
        
          1
        
        
          "
        
        );
        
          return
        
        
          ;}


        
        
          163
        
             dfs(
        
          1
        
        ,
        
          1
        
        
          );


        
        
          164
        
        
              get_det();


        
        
          165
        
             n-=(
        
          long
        
        
          long
        
        
          )m;


        
        
          166
        
        
          while
        
        
          (n)


        
        
          167
        
        
              {


        
        
          168
        
        
          if
        
        (n&(1LL)) ans=zy*
        
          ans;


        
        
          169
        
                 zy=zy*
        
          zy;


        
        
          170
        
                 n>>=
        
          1LL;


        
        
          171
        
        
              }


        
        
          172
        
             printf(
        
          "
        
        
          %lld\n
        
        
          "
        
        ,ans.mt[hash[
        
          0
        
        ]][
        
          1
        
        
          ]);


        
        
          173
        
        
          }


        
        
          174
        
        
          175
        
        
          int
        
        
           main()


        
        
          176
        
        
          {


        
        
          177
        
        
              go();


        
        
          178
        
        
          return
        
        
          0
        
        
          ;


        
        
          179
        
         }
      

?

?

BZOJ 1494 [NOI2007]生成樹計數 矩陣乘法+DP


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日韩精品一区二区三区免费观看 | 午夜精品久久久久久久男人的天堂 | 免费啪视频在线观看免费的 | 免费看污又色又爽又黄视频 | 天天操天天操天天操天天操 | 欧美日韩午夜精品 | 青青草免费观看完整版高清 | 精品一区二区高清在线观看 | 5月激情网| 亚洲美女综合 | 亚洲精品乱码久久久久久 | 春宵福利网站在线观看 | 国产精品乱码一区二三区小蝌蚪 | 国产激情一区二区三区四区 | 小明永久成人一区二区 | 亚洲色综合图区p | 久久97精品久久久久久久看片 | 久久综合九色综合欧洲色 | 羞羞视频网站在线观看 | 久久久9999久久精品小说 | 久久久国产精品福利免费 | 色噜噜狠狠网站 | 亚州av在线 | 男女生性毛片免费观看 | 99riav9.vip | 久久久久久久国产精品毛片 | 亚洲国产一区二区视频 | 成年网站视频在线观看 | 久草精品视频在线观看 | 婷婷在线观看网站 | 欧美伊人 | 亚洲3atv精品一区二区三区 | 鲁一鲁影院 | 99国产精品2018视频全部 | 亚洲欧美一区二区三区情侣bbw | 欧美αv | 欧美五月 | 国内精品久久久久久99蜜桃 | 欧美日韩国产综合视频在线看 | 婷婷色在线 | 五月天国产视频 |