BZOJ 3120 Line【矩阵乘法优化dp

来源:互联网 发布:戴斯蒙德.道斯 知乎 编辑:程序博客网 时间:2024/04/30 05:25

矩阵乘法写到想哭【

感觉不会再爱了x

我失去了信仰【x


看到数据范围,和题面,觉得多半是个矩乘优化dp【虽然这个不太靠谱2333反正刚才当场被yjq大爷打脸】


这些都不管嘛先yy一下转移,

因为限制有两个,

如果用0表示女孩子,1表示男孩子的话【并没有别的意思23333

则限制分别是横着连续的1的个数以及全是1的列的列数【对不起我m和n看反了但是不影响嘛2333


反正辣鸡flaze先yy了一下f[i][j][s],表示算到了第i列,已经有了j列全是1的,当前列的状态是s(s的状态是2^8)的,反正行数足够小(x),然后发现转移十分的坑爹……看起来是要T的不要不要的而且似乎好像很难写

于是深思熟虑后选择GG……【当时并没有注意到PQ都是小于等于3的】于是看到题解的大爷们说的……

用f[i][j][a][b]记录

算到了第i列,已经有了j列全1,从第i列往前的三列里是000的有a个,001的有b个(显然011的就是(m-a-b)个了)

转移的话……自己YY一下就好,反正组合数也不大,可以直接在程序里算(我就打个表玩一下而已【滚地

发现递推的时候,f[i]只和f[i-1]有关,于是把转移扔到矩阵里面,直接pow就好了

目测转移矩阵有点稀疏,于是在把三维的状态压成一维的时候,根据某大爷的blog优化一下(反正看到代码一眼懂)【反正当时我是WA的欲仙欲死而且完全不知道怎么改

构建转移矩阵的部分……是向某位大爷学习了一波的【传送门】……


热爱列向量的我……表示……我家矩阵的d[i][j]表示从j转移到i【懵逼


对了……有个谜一般的问题……在struct里面开了long long d[256][256]就会直接RE……(而且是win下RE,linux下跑的飞起)……

//=========================================下面是吐槽================================================================

于是今天一上午就这样荒废了【x】↓……

①卸载dev ②安装新的dev ③安装vim ④卸载dev ⑤上ccf官网下载g++ ⑥下载gdb ⑦又下载一个dev ⑧卸载刚才下载的g++ ⑨卸载gdb

然后觉得自己电脑出事了于是去用机房的老爷机发现会跪,万念俱灰想起了cf的在线编译器,发现跑得健步如飞【x】,【懵逼脸ing】于是听yjq的去uoj在线跑了一波,依然健步如飞…………沉思…………找到某用linux颓废的同学跑一跑……健步如飞…………【一脸懵逼_Flaze_ver.gif】

反正……数组开小点就不RE了【滚地】

//==================================================================================================================


#include<cstdio>#include<cstring>#define MOD 1000000007#define MAXT 200using namespace std;int p,m,Q;long long n;const int C[9][9]={{1,0,0,0,0,0,0,0,0},{1,1,0,0,0,0,0,0,0},{1,2,1,0,0,0,0,0,0},{1,3,3,1,0,0,0,0,0},{1,4,6,4,1,0,0,0,0},{1,5,10,10,5,1,0,0,0},{1,6,15,20,15,6,1,0,0},{1,7,21,35,35,21,7,1,0},{1,8,28,56,70,56,28,8,1}};struct matrix{int x,y,d[MAXT][MAXT];void write(){for(int i=1;i<=x;++i){for(int j=1;j<=y;++j)printf("%d ",d[i][j]);puts("");}puts("");}matrix(){x=y=0,memset(d,0,sizeof d);}matrix(int a):x(a),y(a){memset(d,0,sizeof d);for(int i=1;i<=a;++i)d[i][i]=1;}matrix(int a,int b):x(a),y(b){memset(d,0,sizeof d);}matrix operator * (const matrix &ano){matrix RTN(x,ano.y);for(int i=1;i<=x;++i)for(int j=1;j<=y;++j)if(d[i][j])for(int k=1;k<=ano.y;++k)if(ano.d[j][k])RTN.d[i][k]=(0ll+RTN.d[i][k]+1ll*d[i][j]*ano.d[j][k])%MOD;return RTN;}}A,B;matrix pow(matrix TMP,long long cf){matrix RTN(TMP.x);for(;cf;cf>>=1){if(cf&1)RTN=RTN*TMP;TMP=TMP*TMP;}return RTN;}struct yjq{int a,b,c;yjq(){}yjq(int a,int b,int c):a(a),b(b),c(c){}}que[MAXT];int cnt=0;void build_B(){for(int i=0;i<=Q;++i)for(int j=0;j<=m;++j)for(int k=0;k<=m-j;++k){int rs=m-j-k;if(p==2&&rs)continue;que[++cnt]=yjq(i,j,k);if(i==0&&j==m&&k==0)A.d[cnt][1]=1;}B=matrix(cnt,cnt),A.x=cnt,A.y=1;for(int i=1;i<=cnt;++i)for(int j=1;j<=cnt;++j){int l1=que[i].a,a1=que[i].b,b1=que[i].c,c1=m-a1-b1;int l2=que[j].a,a2=que[j].b,b2=que[j].c,c2=m-a2-b2;if(l2<l1 || l2>l1+1)continue;if(l1==l2){if(b2>a1||c2>b1)continue;B.d[j][i]=1ll*C[a1][b2]*C[b1][c2]%MOD;if(b2==a1 && c2==b1 && a1+b1==m)B.d[j][i]=0;}elseif((!a2)&&(!c1)&&(c2==b1)&&(b2==a1))B.d[j][i]=1;}}int main(){scanf("%d%lld%d%d",&m,&n,&p,&Q);if(p<=1)return puts("1"),0;build_B();A=pow(B,n)*A;long long ans=0;for(int i=1;i<=cnt;++i)ans=(ans+A.d[i][1])%MOD;printf("%lld",ans);return 0;}


0 0
原创粉丝点击