日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bzoj 3120 矩阵优化DP

發布時間:2025/4/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj 3120 矩阵优化DP 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

我的第一道需要程序建矩陣的矩陣優化DP。

?

題目可以將不同的p分開處理。

對于p==0 || p==1 直接是0或1

對于p>1,就要DP了。這里以p==3為例:

設dp[i][s1][s2][r]為前i列,結尾為0的有s1行(0表示女生,1表示男生),結尾為01的有s2個,結尾為011的有n-s1-s2個,有r列全是1的方案數。

狀態這么復雜,看起來一點也不能用矩陣優化,但我們可以將狀態(s1,s2,r)hash成整數,然后建立狀態之間的轉移。

?

收獲:

這種m超過10^7的一般都要用矩陣優化,如果狀態很復雜,可以將復雜的狀態(但一般不多)hash成整數,然后用計算機建立狀態之間的轉移,然后就可以用矩陣優化了。

?

?

1 /************************************************************** 2 Problem: 3120 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:24504 ms 7 Memory:2616 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #define M 1000000007 13 #define maxs 200 14 15 typedef long long dint; 16 17 int n, p, q; 18 dint m; 19 int comb[10][10]; 20 21 void init_comb() { 22 for( int i=0; i<=9; i++ ) 23 for( int j=0; j<=i; j++ ) { 24 if( j==0 || i==j ) 25 comb[i][j]=1; 26 else 27 comb[i][j] = (comb[i-1][j]+comb[i-1][j-1]); 28 } 29 } 30 struct Matrix { 31 int n; 32 dint v[maxs][maxs]; 33 void init( int nn ) { 34 n=nn; 35 for( int i=0; i<n; i++ ) 36 for( int j=0; j<n; j++ ) 37 v[i][j]=0; 38 } 39 void make_unit( int nn ) { 40 n=nn; 41 for( int i=0; i<n; i++ ) 42 for( int j=0; j<n; j++ ) 43 v[i][j] = i==j; 44 } 45 Matrix operator*( const Matrix & b ) const { 46 const Matrix & a = *this; 47 Matrix rt; 48 memset( &rt, 0, sizeof(rt) ); 49 rt.n = b.n; 50 for( int k=0; k<n; k++ ) { 51 for( int i=0; i<n; i++ ) { 52 if( a.v[i][k] ) { 53 for( int j=0; j<n; j++ ) { 54 if( b.v[k][j] ) { 55 rt.v[i][j] += (a.v[i][k]*b.v[k][j])%M; 56 if( rt.v[i][j]>=M ) rt.v[i][j]-=M; 57 } 58 } 59 } 60 } 61 } 62 /* 63 for( int i=0; i<n; i++ ) { 64 for( int j=0; j<n; j++ ) { 65 rt.v[i][j] = 0; 66 for( int k=0; k<n; k++ ) { 67 rt.v[i][j] += (a.v[i][k]*b.v[k][j])%M; 68 if( rt.v[i][j]>=M ) 69 rt.v[i][j]-=M; 70 } 71 } 72 } 73 */ 74 return rt; 75 } 76 }; 77 78 Matrix mpow( Matrix a, dint b ) { 79 Matrix rt; 80 for( rt.make_unit(a.n); b; b>>=1,a=a*a ) 81 if( b&1 ) rt=(rt*a); 82 return rt; 83 } 84 namespace Sec1 { 85 void sov(){ 86 if( p==0 ) printf( "0\n" ); 87 else if( p==1 ) printf( "1\n" ); 88 } 89 } 90 namespace Sec2 { 91 int info[maxs][3], idx[9][4], tot; 92 Matrix trans; 93 void init() { 94 for( int r=0; r<=q; r++ ) 95 for( int a=0; a<=n; a++ ) { 96 info[tot][0] = a; 97 info[tot][1] = n-a; 98 info[tot][2] = r; 99 idx[a][r] = tot; 100 tot++; 101 } 102 trans.init(tot); 103 for( int s=0; s<tot; s++ ) { 104 int a=info[s][0], r=info[s][2]; 105 for( int sa=0; sa<=a; sa++ ) { 106 int na=n-sa, nr=r+(sa==n); 107 if( nr>q ) continue; 108 int ns=idx[na][nr]; 109 trans.v[s][ns] = comb[a][sa]; 110 } 111 } 112 } 113 void sov() { 114 init(); 115 trans = mpow( trans, m ); 116 int row = idx[n][0]; 117 dint ans=0; 118 for( int i=0; i<tot; i++ ) { 119 ans += trans.v[row][i]; 120 if( ans>=M ) ans-=M; 121 } 122 printf( "%lld\n", ans ); 123 } 124 } 125 namespace Sec3 { 126 int info[maxs][4], idx[9][9][4], tot; 127 Matrix trans; 128 void init() { 129 for( int r=0; r<=q; r++ ) 130 for( int a=0; a<=n; a++ ) 131 for( int b=0; b<=n-a; b++ ) { 132 info[tot][0] = a; 133 info[tot][1] = b; 134 info[tot][2] = n-a-b; 135 info[tot][3] = r; 136 idx[a][b][r] = tot; 137 tot++; 138 } 139 trans.n = tot; 140 for( int s=0; s<tot; s++ ) { 141 int a=info[s][0], b=info[s][1], c=info[s][2], r=info[s][3]; 142 for( int sa=0; sa<=a; sa++ ) 143 for( int sb=0; sb<=b; sb++ ) { 144 int na=c+a-sa+b-sb, nb=sa, nr=r+(sa+sb==n); 145 if( nr>q ) continue; 146 int ns = idx[na][nb][nr]; 147 trans.v[s][ns] = comb[a][sa]*comb[b][sb]; 148 } 149 } 150 } 151 void sov(){ 152 init(); 153 trans = mpow( trans, m ); 154 int row = idx[n][0][0]; 155 dint ans=0; 156 for( int i=0; i<tot; i++ ) { 157 ans += trans.v[row][i]; 158 if( ans>=M ) ans-=M; 159 } 160 printf( "%lld\n", ans ); 161 } 162 } 163 164 int main() { 165 scanf( "%d%lld%d%d", &n, &m, &p, &q ); 166 init_comb(); 167 if( p<=1 ) Sec1::sov(); 168 else if( p==2 ) Sec2::sov(); 169 else if( p==3 ) Sec3::sov(); 170 } View Code

?

轉載于:https://www.cnblogs.com/idy002/p/4316145.html

總結

以上是生活随笔為你收集整理的bzoj 3120 矩阵优化DP的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。