YY模拟:棋盘(FFT)

22人阅读 评论(0) 收藏 举报
分类:

题意:
给定nm的棋盘(n3,m1e5),给定k,问有多少种染色方案使得最终棋盘的黑色联通块恰好k(mod998244353)

题解:
n=3,我们可以状压DP,记fi,j,k表示DP到i列,状态为j,联通块为k的方案数。

显然我们有O(mk92)的做法,不过我们可以用生成函数+矩阵乘法来优化。

最终答案是nm2次多项式,我们带入这么多个点来求点值做DFT,每次点值就可以直接矩乘递推了,时间复杂度为O(nm293).

最后做FFT,总时间复杂度为O(nm2(93+lognm2)),注意卡常。

(其实不用卡常,真正的有效状态只有7种,不过太懒就不写了。。)

#include <bits/stdc++.h>
using namespace std; 
typedef unsigned long long ULL;

const int N=233333*2, mod=998244353, G=3;
const ULL LIM=(ULLONG_MAX/mod-mod)*mod;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (ULL)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}
inline int inv(int a) {return power(a,mod-2);}
#define P(a,b) power(a,b)
int n,m,k,K,L,pos[N],W[N],yc[N];
inline void dft(int *a) {
    for(int i=1;i<k;i++) pos[i]=(i&1) ? ((pos[i>>1]>>1)^(k>>1)) : (pos[i>>1]>>1);
    for(int i=1;i<k;i++) if(pos[i]>i) swap(a[pos[i]],a[i]);
    for(int bl=1;bl<k;bl<<=1) {
        int tl=bl<<1, wn=power(G,(mod-1)/tl);
        W[0]=1; for(int i=1;i<bl;i++) W[i]=mul(W[i-1],wn);
        for(int bg=0;bg<k;bg+=tl)
            for(int j=0;j<bl;j++) {
                int &t1=a[bg+j], &t2=a[bg+j+bl], t=mul(t2,W[j]);
                t2=dec(t1,t); t1=add(t1,t);
            }
    }
}
struct matrix {
    ULL a[10][10];
    matrix() {}
    matrix(int t) {
        memset(a,0,sizeof(a));
        for(int i=0;i<=L;i++) a[i][i]=t;
    }
    friend inline matrix operator *(const matrix &a,const matrix &b) {
        matrix c(0);
        for(int i=0;i<=L;i++)
            for(int k=0;k<=L;k++) if(a.a[i][k])
                for(int j=0;j<=L;j++)
                    if((c.a[i][j]+=a.a[i][k]*b.a[k][j])>=LIM) c.a[i][j]%=mod;
        for(int i=0;i<=L;i++)
            for(int j=0;j<=L;j++)
                if(c.a[i][j]>=mod) c.a[i][j]%=mod;
        return c;
    }
    friend inline matrix operator ^(matrix a,int b) {
        matrix rs(1);
        for(;b;b>>=1,a=a*a) if(b&1) rs=rs*a;
        return rs;
    }
}pw;
#define opt() for(int i=0;i<=L;++i)\
                  for(int j=0;j<=L;++j)\
                       pw.a[i][j]=tp[i][j]
inline int getval(int w) {
    if(L==1) {
        int tp[2][2]={ {1,w},
                       {1,1} }; 
        opt();
    } else if(L==3) {
        int tp[4][4]={ {1,w,w,w},
                       {1,1,w,1},
                       {1,w,1,1},
                       {1,1,1,1} };
        opt();
    } else {
        int tp[9][9]={ {1,w,w,w,w,P(w,2),w,w,0},
                       {1,1,w,1,w,w,w,1,0},
                       {1,w,1,1,w,P(w,2),1,1,0},
                       {1,1,1,1,w,w,1,1,0},
                       {1,w,w,w,1,w,1,1,0},
                       {1,1,w,1,1,1,1,inv(w),0}, 
                       {1,w,1,1,1,w,1,1,0}, 
                       {1,1,1,1,1,0,1,1,1}, 
                       {1,1,w,1,1,0,1,1,1}, };
        opt();
    }
    matrix A(0); 
    A.a[0][0]=1;
    A=A*(pw^m);
    int ans=0;
    for(int i=0;i<=L;++i) ans=add(ans,A.a[0][i]);
    return ans;
}
inline int solve() {
    for(k=1; k<=(n*m)/2+2;k<<=1);
    int wn=power(G,(mod-1)/k), w=1;
    for(int i=0;i<k;i++) 
        yc[i]=getval(w), w=mul(w,wn);
    dft(yc); reverse(yc+1,yc+k); 
    const int iv=power(k,mod-2);
    return mul(yc[K],iv);
}
int main() {
    cin>>n>>m>>K;
    L=((n==1) ? 1 : ((n==2) ? 3 : 8));
    cout<<solve();
}
查看评论

YY模拟器

  • 2013年06月09日 13:38
  • 612KB
  • 下载

模拟棋盘

/* * 烟台大学计算机学院学生 *All right reserved. *文件名称:java *作者:孔云 *完成日期:201...
  • u012369559
  • u012369559
  • 2014-11-23 15:46:46
  • 709

海面模拟以及渲染(计算着色器、FFT、Reflection Matrix)

一、海面网格的波形计算 详见:OCEAN SIMULATION PART ONE: USING THE DISCRETE FOURIER TRANSFORM 大体思路:  如上图公式...
  • xiewenzhao123
  • xiewenzhao123
  • 2018-01-19 22:55:19
  • 156

[FFT 压位] Hillan模拟赛 A.简单字符串匹配

前几个点么 标算给的分块FFT n^1.5 logn 我怎么打都不过 压压位开氧气卡过去 最后一个点么 把A串转过来 FFT #include #include #include #include...
  • u014609452
  • u014609452
  • 2016-10-23 10:23:00
  • 435

【NOIP2012模拟10.6】填充棋盘

Description横一划竖一划,横一划竖一划…………小R画出了一个n*m的棋盘。 由于NOIP快要到了,小R有了一个奇妙的想法。 在棋盘的每一个小方格中填入N,O,I,P这4个字母中的一个,若棋盘...
  • peter_zhu01
  • peter_zhu01
  • 2016-10-04 21:54:58
  • 460

BJ模拟:stwell(BFS)

从前有一只鸽子。它生活在一个 N×MN \times MN×M 的网格里。网格从 000 开始标号, 有些网格是山,剩下的是平地。 他最开始在(stx,sty)(stx,sty)(stx,sty...
  • qq_35649707
  • qq_35649707
  • 2017-12-10 21:15:25
  • 98

海洋模拟

http://www.cnblogs.com/wubugui/p/4541812.html?utm_source=tuicool&utm_medium=referral 本文基于[J...
  • pizi0475
  • pizi0475
  • 2016-11-29 15:39:06
  • 1430

fft的vc模拟以及wav文件的波形解析

  • 2016年03月25日 10:59
  • 1.92MB
  • 下载

【jzoj5306】【NOIP2017提高A组模拟8.18】【棋盘游戏】

description这个游戏上在一个无限大的棋盘上, 棋盘上只有一颗棋子在位置(x,y)(x,y>=0)棋盘的左下角是(0,0)Amphetamine每次都是第一个移动棋子,然后Amphetamin...
  • chunkitlau
  • chunkitlau
  • 2017-08-18 20:25:51
  • 147

hdu5386 棋盘涂色模拟

http://acm.hdu.edu.cn/showproblem.php?pid=5386 Problem Description You have an n∗n matrix.Every ...
  • u013573047
  • u013573047
  • 2015-08-14 11:04:43
  • 941
    个人资料
    持之以恒
    等级:
    访问量: 6万+
    积分: 4585
    排名: 8042
    友情链接
    文章分类