Gym 100917M Matrix, The(状压dp)
Posted 吃花椒的妙酱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gym 100917M Matrix, The(状压dp)相关的知识,希望对你有一定的参考价值。
题目大意:给n,a,b,q。一个n行n列矩阵,当且仅当每行有[a,b]个1且每列有一段连续的1才是合法的,q次询问,问第t字典序大的矩阵的样子,a,b,n<=10,t<=1e18,q<=1000
思路:牛逼题,像数位dp的思路。画张图理解一下。
上图,s表示每行的状态,当si->sj的转移是合法的时候我们才向下面连边(上图默认都是合法的了),可以发现很多状态都是重复的,和数位dp一样的思路——记忆化搜索。
我们用dp[r][state][mask]表示第r行状态为state,mask表示从1~r行每列是否出现过1的方案数。求来后,对于询问第t个,我们只要每层按照字典序搜过去就解决了。
接下来看转移方程,发现“每列一段连续1这个条件不好处理”,所以我们引入mask参数,表示1~r行的每列是否出现过1,可以发现不合法的情况是,
如何,下一行出现1,本行有0,之前出现过了1,这样就好判断相邻两行间转移了。
dp[r][state][mask] -> dp[r+1][next_state][next_state | mask]。
牛逼题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false),cin.tie(0)
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pii pair<int ,int >
#define pb(v) push_back(v)
#define all(v) v.begin(),v.end()
#define int long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define endl "\\n"
#define fi first
#define se second
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define AC return 0
const int N=1e5+10;
const int mod=1e9+7;
const double eps=1e-8;
int n,a,b,q;
int ans[11];
int f[11][1<<10][1<<10];
std::vector<int> V;//合法状态
//mask 表示到r行,每列是否出现过1
int dfs1(int r,int sta ,int mask)
int &temp = f[r][sta][mask];
if( temp>-1 ) return temp;
if( r==n )
return temp = mask==((1<<n)-1);//每列至少一个1
temp = 0;
for(int nxt:V)
//不合法的情况就是有
//1
//0,,中间可能有若干0
//1这种情况
if( mask&(~sta)&nxt) continue;
temp += dfs1(r+1,nxt,nxt|mask);
return temp;
bool dfs2(int k,int r,int sta,int mask)
if( r==n ) return true;
for(int nxt:V)
if( mask&(~sta)&nxt) continue;
if( k <= f[r+1][nxt][nxt|mask] )
ans[r+1] = nxt;
return dfs2(k,r+1,nxt,nxt|mask);
else k -= f[r+1][nxt][nxt|mask];
return false;
signed main()
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
IOS;
mst(f,-1);
cin>>n>>a>>b>>q;
for(int i=1 ;i<(1<<n) ;i++)
int cnt=0;
for(int j=0 ;j<n ;j++) cnt += i>>j&1;
if( a<=cnt && cnt<=b ) V.push_back(i);
dfs1(0,0,0);
while( q-- )
int x;cin>>x;
if( dfs2(x,0,0,0) )
_for(i,1,n)
for(int j=n-1 ;j>=0 ;j--) cout<<(ans[i]>>j&1);
cout<<endl;
cout<<endl;
else
cout<<"No such matrix."<<endl;
AC;
以上是关于Gym 100917M Matrix, The(状压dp)的主要内容,如果未能解决你的问题,请参考以下文章
Gym 101194L / UVALive 7908 - World Cup - [三进制状压暴力枚举][2016 EC-Final Problem L]
Codeforces Gym101341I:Matrix God(随机化构造矩阵降维)***
gym101964 G.Matrix Queries(思维+线段树)
gym101964G Matrix Queries seerc2018g题 数学归纳法+线段树(递归)