【GDOI2018模拟7.8】矩阵
这是一道做法显然的状压DP
先看题意, 题目让我们求使得一个已有
k
个点被钦定的
有一个数据
n
、用PY想想就知道答案显然为零。
1. 最 naive 的想法,状压一维,扫另一维,问题就可以在 nm2min(n,m) 的时间内求解。
台下的吃瓜群众们:“然而无论是
n
还是
2.
是时候考察
k
了。我们发现
那列的数量级如何缩小呢?
3.
我们找出所有列构成
B
使得每一列都存在那
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<assert.h>
#include<cstring>
#include<vector>
using namespace std;
#define re_ return
#define in_ inline
#define st_ static
#define op_ operator
#define co_ const
#define ct_ continue
#define br_ break
#define tp_ template
#define tn_ typename
#define gc() getchar()
#define inc(l, i, r) for(i=l; i<r; ++i)
#define dec(r, i, l) for(i=r; i>l; --i)
#define mp(a, b) make_pair(a, b)
#define fr_ first
#define sc_ second
#define let(a, b) st_ ll a; a=b
typedef long long ll;
tp_<tn_ x> in_ ll mxe(x& a, x b) {re_ a<b?(a=b, 1):0;}
tp_<tn_ x> in_ ll mne(x& a, x b) {re_ a>b?(a=b, 1):0;}
struct io
{
in_ ll op_ !(void)
{
st_ ll s, r, c;
for(s=1, r=0; (c=gc())<48||57<c;)
if(c=='-') s=-1;
for(;c>47&&58>c; c=gc())
r=10*r+c-48;
return s*r;
}
in_ io& op_ & (ll& a)
{re_ a=!(*this), *this;}
in_ io& op_ | (co_ char* s)
{re_ printf("%s", s), *this;}
in_ io& op_ | (ll a)
{re_ printf("%I64d ", a), *this;}
in_ io& op_ ^ (ll a)
{re_ printf("%I64d\n", a), *this;}
} jio;
co_ ll mxn=100001, mxm=200002, mxk=2000002, mod=998244353;
bool cvr[mxn];
ll
n, nn, m, anum[mxn], acnt[66], apos[66][2], acol[66],
tb, bline[mxm],
mm, cline[mxm], c[30][30], cxor[66],
f[30][13][1<<10][2];
vector<pair<ll, ll> > fxd[mxm];
in_ ll pw0(ll a, ll b)
{
st_ ll r;
for(r=1; b; a=a*a%mod, b>>=1)
b&1?r=r*a%mod:0;
re_ r;
}
in_ ll pw(ll b)
{
st_ ll r, a;
for(r=1, a=2; b; a=a*a%mod, b>>=1)
b&1?r=r*a%mod:0;
re_ r;
}
int main()
{
freopen("matrix2.in", "r", stdin);
freopen("1.out", "w", stdout);
ll i, j, k, l, x, ans=1;
if(jio&n, n==2333)
re_ jio^0, 0;
jio&m&k;
inc(0, i, k)
jio&x&l&j, fxd[l].push_back(mp(x, j));
//---------------------------------------------
#define siz(i) fxd[i].size()
#define yco(i, j) fxd[i][j].fr_
#define col(i, j) fxd[i][j].sc_
inc((x=1, 2), i, m+1)
if(siz(i)<siz(x))
x=i;
nn=siz(x);
inc(0, i, nn)
anum[yco(x, i)]=i+1;
inc(1, i, m+1) if(i^x)
{
inc(k=0, j, siz(i))
k+=anum[yco(i, j)]>0;
if((l=n-nn-siz(i)+k-1)>=0)
bline[tb++]=i, ans=ans*pw(l)%mod;
else
cline[mm++]=i;
}
//---------------------------------------------
inc(1, i, nn+1)
acol[i]=col(x, i-1);
inc(0, i, tb)
{
let(bi, bline[i]);
inc(0, j, siz(bi))
{
cvr[k=anum[yco(bi, j)]]=1;
if(k) acol[k]^=col(bi, j);
}
inc(1, j, nn+1)
{
if(!cvr[j]) ++acnt[j];
}
inc(0, j, siz(bi))
cvr[anum[yco(bi, j)]]=0;
}
inc(1, i, nn+1)
if(acnt[i])
apos[i][0]=apos[i][1]=pw(acnt[i]-1);
else
apos[i][acol[i]]=1;
//---------------------------------------------
inc(0, i, mm)
{
let(ci, cline[i]);
cxor[i+1]=0;
inc(0, j, siz(ci))
if(k=anum[yco(ci, j)])
c[i+1][k]=col(ci, j)+1;
else
cxor[i+1]^=col(ci, j);
}
f[1][0][0][cxor[1]]=1;
inc(1, i, mm+1)
{
#define upd(a, b) (a=(a+(b))%mod)
#define updf(a) upd(a, f[i][j-1][k][l])
inc(1, j, nn+1)
inc(0, k, 1<<nn)
inc(0, l, 2)
{
if(c[i][j]<2)
updf(f[i][j][k][l]);
if(c[i][j]!=1)
updf(f[i][j][k^1<<j-1][l^1]);
}
ll a=0;
inc(0, k, 1<<nn)
f[i+1][0][k][cxor[i+1]]=f[i][nn][k][1];
}
inc(l=0, k, 1<<nn)
{
inc((j=f[mm+1][0][k][0], 1), i, nn+1)
j=j*apos[i][k>>i-1&1^1]%mod;
l+=j;
}
jio^l*ans%mod;
re_ 0;
}
//记得取模