QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#644011#8173. T Tile Placement Countingrqoi031AC ✓597ms7680kbC++2010.9kb2024-10-16 09:38:052024-10-16 09:38:05

Judging History

你现在查看的是最新测评结果

  • [2024-10-16 09:38:05]
  • 评测
  • 测评结果:AC
  • 用时:597ms
  • 内存:7680kb
  • [2024-10-16 09:38:05]
  • 提交

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