QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#644011 | #8173. T Tile Placement Counting | rqoi031 | AC ✓ | 597ms | 7680kb | C++20 | 10.9kb | 2024-10-16 09:38:05 | 2024-10-16 09:38:05 |
Judging History
answer
#include<stdio.h>
#include<algorithm>
#include<numeric>
#include<random>
#include<chrono>
typedef unsigned int uint;
typedef unsigned long long ull;
constexpr uint mod{998244353};
constexpr uint plus(const uint &x,const uint &y) {
if(x+y>=mod) {
return x+y-mod;
}
return x+y;
}
constexpr uint minus(const uint &x,const uint &y) {
if(x<y) {
return x-y+mod;
}
return x-y;
}
constexpr uint power(uint x,uint y) {
uint s(1);
while(y>0) {
if(y&1) {
s=ull(s)*x%mod;
}
x=ull(x)*x%mod;
y>>=1;
}
return s;
}
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
template<typename Tp>
inline Tp rand(const Tp &l,const Tp &r) {
return std::uniform_int_distribution<Tp>(l,r)(rng);
}
constexpr bool check(const uint &n,const uint &s) {
int j(0);
for(uint i=0;i!=n;i++) {
if((j+=s>>i&1?1:-1)<0) {
return false;
}
}
return j==0;
}
uint id[1<<14|1];
constexpr uint maxn{429};
struct matrix {
uint n;
uint a[maxn][maxn];
constexpr matrix():n{},a{} {}
constexpr matrix(const uint &_n):n{_n},a{} {}
constexpr void clear() {
for(uint i=0;i!=n;i++) {
for(uint j=0;j!=n;j++) {
a[i][j]=0;
}
}
}
constexpr void resize(const uint &_n) {
n=_n,clear();
}
constexpr matrix mul(const matrix &x) const {
matrix z(x.n);
for(uint i=0;i!=z.n;i++) {
for(uint j=0;j!=z.n;j++) {
for(uint k=0;k!=z.n;k++) {
z.a[i][k]=(z.a[i][k]+ull(a[i][j])*x.a[j][k])%mod;
}
}
}
return z;
}
constexpr matrix &rmul(const matrix &x) {
const matrix y(*this);
clear();
for(uint i=0;i!=n;i++) {
for(uint j=0;j!=n;j++) {
for(uint k=0;k!=n;k++) {
a[i][k]=(a[i][k]+ull(y.a[i][j])*x.a[j][k])%mod;
}
}
}
return *this;
}
constexpr matrix &lmul(const matrix &x) {
const matrix y(*this);
clear();
for(uint i=0;i!=n;i++) {
for(uint j=0;j!=n;j++) {
for(uint k=0;k!=n;k++) {
a[i][k]=(a[i][k]+ull(x.a[i][j])*y.a[j][k])%mod;
}
}
}
return *this;
}
constexpr matrix &square() {
const matrix y(*this);
clear();
for(uint i=0;i!=n;i++) {
for(uint j=0;j!=n;j++) {
for(uint k=0;k!=n;k++) {
a[i][k]=(a[i][k]+ull(y.a[i][j])*y.a[j][k])%mod;
}
}
}
return *this;
}
};
struct vector {
uint n;
uint a[maxn];
constexpr vector():n{},a{} {}
constexpr vector(const uint &_n):n{_n},a{} {}
constexpr void clear() {
for(uint i=0;i!=n;i++) {
a[i]=0;
}
}
constexpr void resize(const uint &_n) {
n=_n,clear();
}
constexpr vector &lmul(const matrix &x) {
const vector y(*this);
clear();
for(uint i=0;i!=n;i++) {
for(uint j=0;j!=n;j++) {
a[i]=(a[i]+ull(x.a[i][j])*y.a[j])%mod;
}
}
return *this;
}
constexpr uint dot(const vector &x) const {
uint s(0);
for(uint i=0;i!=n;i++) {
s=(s+ull(a[i])*x.a[i])%mod;
}
return s;
}
};
namespace dsu {
uint fa[60];
inline void init(const uint &n) {
std::iota(fa,fa+n,0);
}
uint getf(const uint &x) {
return fa[x]==x?x:fa[x]=getf(fa[x]);
}
inline void merge(const uint &x,const uint &y) {
fa[getf(y)]=getf(x);
}
}
namespace linear {
constexpr uint N{860};
inline uint BM(const uint &n,const uint *const f,uint *const g) {
static uint h[N+5]{},_h[N+5]{};
std::fill(g,g+n+1,0);
std::fill(h,h+n+1,0);
uint pos(-1),lst(0),del(0);
uint len(0);
for(uint i=1;i<=n;i++) {
uint tmp(0);
for(uint j=1;j<=len;j++) {
tmp=(tmp+ull(f[i-j])*g[j])%mod;
}
if(tmp==f[i]) {
continue;
}
if(pos==-1) {
len=i,pos=i;
del=f[i];
continue;
}
const uint _del(minus(f[i],tmp));
const uint coef(ull(_del)*power(del,mod-2)%mod);
del=_del;
std::copy(g,g+len+1,_h);
for(uint j=1;j<=lst;j++) {
g[j+i-pos]=(g[j+i-pos]+ull(mod-coef)*h[j])%mod;
}
g[i-pos]=plus(g[i-pos],coef);
std::tie(lst,len)=std::make_tuple(len,std::max(len,lst+i-pos));
std::copy(_h,_h+lst+1,h);
pos=i;
}
return len;
}
}
namespace poly {
constexpr uint N{430};
inline void multiply(const uint &n,const uint *const f,const uint *const g,uint *const h) {
std::fill(h,h+(n<<1),0);
for(int i=0;i!=n;i++) {
for(int j=0;j!=n;j++) {
h[i+j]=(h[i+j]+ull(f[i])*g[j])%mod;
}
}
}
inline void modulo(const uint &n,const uint &m,const uint *const f,const uint *const g,uint *const h) {
std::copy(f,f+n,h);
uint _m(m);
while(_m!=0&&g[_m-1]==0) {
--_m;
}
if(_m==0) {
return;
}
const uint inv(power(g[_m-1],mod-2));
for(uint i=n-1;i!=_m-2;i--) {
const uint coef(ull(mod-h[i])*inv%mod);
for(int j=0;j!=_m;j++) {
h[i+j+1-_m]=(h[i+j+1-_m]+ull(coef)*g[j])%mod;
}
}
}
inline void power(const uint &n,const uint *const f,const uint *const g,uint *const h,const ull &m) {
static uint t0[(N<<1)+5]{},t1[(N<<1)+5];
std::copy(f,f+n,t0);
std::fill(h,h+n,0);
h[0]=1;
for(ull i=m;i;i>>=1) {
if(i&1) {
multiply(n,h,t0,t1);
modulo(n<<1,n,t1,g,h);
}
multiply(n,t0,t0,t1);
modulo(n<<1,n,t1,g,t0);
}
}
}
uint stk[30],tag[30];
int main() {
uint n;ull m;
scanf("%u%llu",&n,&m);
if((n&3)||(m&3)) {
return puts("0"),0;
}
n>>=1,m>>=1;
std::fill(id,id+(1<<n),-1u);
uint tot(0);
for(uint i=0;i!=1<<n;i++) {
if(check(n,i)) {
id[i]=tot++;
}
}
matrix A(tot);
for(uint i=0;i!=1<<n;i++) {
if(id[i]==-1) {
continue;
}
for(uint j=0;j!=1<<(n>>1)-1;j++) {
dsu::init(n<<1);
uint top(0);
for(uint k=0;k!=n;k++) {
if(i>>k&1) {
stk[top++]=k;
}
else {
dsu::merge(k,stk[--top]);
}
}
dsu::merge(0,n);
dsu::merge(n-1,(n<<1)-1);
for(uint k=0;k!=(n>>1)-1;k++) {
if(j>>k&1) {
dsu::merge(k<<1|1,(k<<1|1)+n);
dsu::merge(k+1<<1,(k+1<<1)+n);
}
else {
dsu::merge(k<<1|1,k+1<<1);
dsu::merge((k<<1|1)+n,(k+1<<1)+n);
}
}
uint _i(0);
std::fill(tag,tag+(n<<1),0);
for(uint k=0;k!=n;k++) {
if(!tag[dsu::getf(n+k)]) {
tag[dsu::getf(n+k)]=1,_i|=1<<k;
}
}
uint c(0);
for(uint k=0;k!=n;k++) {
if(!tag[dsu::getf(k)]) {
tag[dsu::getf(k)]=1,++c;
}
}
A.a[id[_i]][id[i]]+=1u<<c;
}
}
matrix B(tot);
for(uint i=0;i!=1<<n;i++) {
if(id[i]==-1) {
continue;
}
for(uint j=0;j!=1<<(n>>1);j++) {
dsu::init(n<<1);
uint top(0);
for(uint k=0;k!=n;k++) {
if(i>>k&1) {
stk[top++]=k;
}
else {
dsu::merge(k,stk[--top]);
}
}
for(uint k=0;k!=n>>1;k++) {
if(j>>k&1) {
dsu::merge(k<<1,(k<<1)+n);
dsu::merge(k<<1|1,(k<<1|1)+n);
}
else {
dsu::merge(k<<1,k<<1|1);
dsu::merge((k<<1)+n,(k<<1|1)+n);
}
}
uint _i(0);
std::fill(tag,tag+(n<<1),0);
for(uint k=0;k!=n;k++) {
if(!tag[dsu::getf(n+k)]) {
tag[dsu::getf(n+k)]=1,_i|=1<<k;
}
}
uint c(0);
for(uint k=0;k!=n;k++) {
if(!tag[dsu::getf(k)]) {
tag[dsu::getf(k)]=1,++c;
}
}
B.a[id[_i]][id[i]]+=1u<<c;
}
}
matrix C(B.mul(A));
vector S(tot);
S.a[([&]()->uint {
uint res(0);
for(uint i=0;i!=n;i+=2) {
res|=1u<<i;
}
return id[res];
}())]=1;
vector _S[(maxn<<1)+3]{};
_S[0]=S;
for(int i=0;i<=tot<<1;i++) {
(_S[i+1]=_S[i]).lmul(C);
}
if((m>>1)-1<=(tot<<1)+1) {
S=_S[(m>>1)-1];
}
else {
vector R(tot);
for(int i=0;i!=tot;i++) {
R.a[i]=rand(1u,mod-1);
}
uint V[(maxn<<1)+5]{},W[(maxn<<1)+5]{};
for(int i=1;i<=(tot<<1)+1;i++) {
V[i]=R.dot(_S[i]);
}
const int len(linear::BM((tot<<1)+1,V,W));
uint f[(maxn<<1)+5]{},g[(maxn<<1)+5]{},h[(maxn<<1)+5]{};
f[1]=1;
for(int i=1;i<=len;i++) {
g[len-i]=minus(0,W[i]);
}
g[len]=1;
poly::power(len+1,f,g,h,(m>>1)-1);
S.clear();
for(int i=0;i!=tot;i++) {
for(int j=0;j<=len;j++) {
S.a[i]=(S.a[i]+ull(_S[j].a[i])*h[j])%mod;
}
}
}
S.lmul(A);
uint ans(0);
for(uint i=0;i!=1<<n;i++) {
if(id[i]==-1) {
continue;
}
dsu::init(n);
uint top(0);
for(uint j=0;j!=n;j++) {
if(i>>j&1) {
stk[top++]=j;
}
else {
dsu::merge(j,stk[--top]);
}
}
for(uint j=0;j!=n>>1;j++) {
dsu::merge(j<<1,j<<1|1);
}
std::fill(tag,tag+n,0);
uint c(0);
for(uint j=0;j!=n;j++) {
if(!tag[dsu::getf(j)]) {
tag[dsu::getf(j)]=1,++c;
}
}
ans=(ans+(ull(S.a[id[i]])<<c))%mod;
}
printf("%u\n",ans);
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 7540kb
input:
4 4
output:
2
result:
ok "2"
Test #2:
score: 0
Accepted
time: 2ms
memory: 7408kb
input:
2 8
output:
0
result:
ok "0"
Test #3:
score: 0
Accepted
time: 2ms
memory: 7464kb
input:
12 3456
output:
491051233
result:
ok "491051233"
Test #4:
score: 0
Accepted
time: 0ms
memory: 7420kb
input:
1 1
output:
0
result:
ok "0"
Test #5:
score: 0
Accepted
time: 2ms
memory: 7428kb
input:
20 999999999999999983
output:
0
result:
ok "0"
Test #6:
score: 0
Accepted
time: 1ms
memory: 7492kb
input:
24 999999999999999994
output:
0
result:
ok "0"
Test #7:
score: 0
Accepted
time: 1ms
memory: 7420kb
input:
24 999999999999999955
output:
0
result:
ok "0"
Test #8:
score: 0
Accepted
time: 591ms
memory: 7628kb
input:
28 999999999999999928
output:
846645622
result:
ok "846645622"
Test #9:
score: 0
Accepted
time: 2ms
memory: 7328kb
input:
28 999999999999999971
output:
0
result:
ok "0"
Test #10:
score: 0
Accepted
time: 1ms
memory: 7252kb
input:
28 999999999999999901
output:
0
result:
ok "0"
Test #11:
score: 0
Accepted
time: 0ms
memory: 7440kb
input:
28 999999999999999945
output:
0
result:
ok "0"
Test #12:
score: 0
Accepted
time: 2ms
memory: 7416kb
input:
30 1000000000000000000
output:
0
result:
ok "0"
Test #13:
score: 0
Accepted
time: 2ms
memory: 7564kb
input:
4 144115188075855868
output:
479168365
result:
ok "479168365"
Test #14:
score: 0
Accepted
time: 2ms
memory: 7384kb
input:
4 288230376151711740
output:
661413713
result:
ok "661413713"
Test #15:
score: 0
Accepted
time: 0ms
memory: 7536kb
input:
4 576460752303423484
output:
854857972
result:
ok "854857972"
Test #16:
score: 0
Accepted
time: 1ms
memory: 7444kb
input:
8 144115188075855868
output:
266363233
result:
ok "266363233"
Test #17:
score: 0
Accepted
time: 1ms
memory: 7540kb
input:
8 288230376151711740
output:
862901307
result:
ok "862901307"
Test #18:
score: 0
Accepted
time: 1ms
memory: 7416kb
input:
8 576460752303423484
output:
455991900
result:
ok "455991900"
Test #19:
score: 0
Accepted
time: 2ms
memory: 7464kb
input:
12 144115188075855868
output:
226857121
result:
ok "226857121"
Test #20:
score: 0
Accepted
time: 0ms
memory: 7464kb
input:
12 288230376151711740
output:
717445399
result:
ok "717445399"
Test #21:
score: 0
Accepted
time: 2ms
memory: 7548kb
input:
12 576460752303423484
output:
935277864
result:
ok "935277864"
Test #22:
score: 0
Accepted
time: 2ms
memory: 7468kb
input:
16 144115188075855868
output:
631950327
result:
ok "631950327"
Test #23:
score: 0
Accepted
time: 0ms
memory: 7540kb
input:
16 288230376151711740
output:
73767413
result:
ok "73767413"
Test #24:
score: 0
Accepted
time: 2ms
memory: 7444kb
input:
16 576460752303423484
output:
329402693
result:
ok "329402693"
Test #25:
score: 0
Accepted
time: 3ms
memory: 7392kb
input:
20 144115188075855868
output:
125405814
result:
ok "125405814"
Test #26:
score: 0
Accepted
time: 3ms
memory: 7552kb
input:
20 288230376151711740
output:
794579293
result:
ok "794579293"
Test #27:
score: 0
Accepted
time: 3ms
memory: 7556kb
input:
20 576460752303423484
output:
726571847
result:
ok "726571847"
Test #28:
score: 0
Accepted
time: 22ms
memory: 7552kb
input:
24 144115188075855868
output:
310529292
result:
ok "310529292"
Test #29:
score: 0
Accepted
time: 22ms
memory: 7564kb
input:
24 288230376151711740
output:
493789216
result:
ok "493789216"
Test #30:
score: 0
Accepted
time: 19ms
memory: 7592kb
input:
24 576460752303423484
output:
606221157
result:
ok "606221157"
Test #31:
score: 0
Accepted
time: 597ms
memory: 7516kb
input:
28 144115188075855868
output:
964541053
result:
ok "964541053"
Test #32:
score: 0
Accepted
time: 593ms
memory: 7588kb
input:
28 288230376151711740
output:
42971353
result:
ok "42971353"
Test #33:
score: 0
Accepted
time: 592ms
memory: 7680kb
input:
28 576460752303423484
output:
179569141
result:
ok "179569141"
Test #34:
score: 0
Accepted
time: 0ms
memory: 7372kb
input:
6 5
output:
0
result:
ok "0"
Test #35:
score: 0
Accepted
time: 2ms
memory: 7492kb
input:
14 28
output:
0
result:
ok "0"
Test #36:
score: 0
Accepted
time: 0ms
memory: 7432kb
input:
25 6365
output:
0
result:
ok "0"
Test #37:
score: 0
Accepted
time: 0ms
memory: 7412kb
input:
18 529543996
output:
0
result:
ok "0"
Test #38:
score: 0
Accepted
time: 2ms
memory: 7364kb
input:
10 675199829716849556
output:
0
result:
ok "0"
Test #39:
score: 0
Accepted
time: 3ms
memory: 7624kb
input:
20 425279816112802872
output:
269059955
result:
ok "269059955"
Test #40:
score: 0
Accepted
time: 0ms
memory: 7532kb
input:
8 38212554426330756
output:
207344318
result:
ok "207344318"
Test #41:
score: 0
Accepted
time: 18ms
memory: 7588kb
input:
24 666881067086698696
output:
245351821
result:
ok "245351821"
Test #42:
score: 0
Accepted
time: 2ms
memory: 7440kb
input:
4 728683474913510792
output:
466882081
result:
ok "466882081"
Test #43:
score: 0
Accepted
time: 593ms
memory: 7484kb
input:
28 201838304882525604
output:
217184228
result:
ok "217184228"
Test #44:
score: 0
Accepted
time: 0ms
memory: 7564kb
input:
4 8560
output:
596875387
result:
ok "596875387"
Test #45:
score: 0
Accepted
time: 2ms
memory: 7564kb
input:
12 60764
output:
930662011
result:
ok "930662011"
Test #46:
score: 0
Accepted
time: 2ms
memory: 7572kb
input:
8 45272
output:
239612337
result:
ok "239612337"
Test #47:
score: 0
Accepted
time: 0ms
memory: 7464kb
input:
8 84616
output:
826857610
result:
ok "826857610"
Test #48:
score: 0
Accepted
time: 0ms
memory: 7564kb
input:
4 316408
output:
529567983
result:
ok "529567983"
Test #49:
score: 0
Accepted
time: 2ms
memory: 7492kb
input:
8 12
output:
1182
result:
ok "1182"
Test #50:
score: 0
Accepted
time: 2ms
memory: 7436kb
input:
8 16
output:
16644
result:
ok "16644"
Test #51:
score: 0
Accepted
time: 0ms
memory: 7568kb
input:
4 8
output:
6
result:
ok "6"
Test #52:
score: 0
Accepted
time: 2ms
memory: 7608kb
input:
12 16
output:
5253822
result:
ok "5253822"
Extra Test:
score: 0
Extra Test Passed