[JZOJ5251]决战
来源:互联网 发布:java面试设计模式 编辑:程序博客网 时间:2024/06/02 16:55
题目大意
给定一个
输入会给定一个
譬如矩阵
表示一个东西上下左右都不能放东西。
请求出恰好放了
题目分析
首先我们可以写出一个很简单的状压
可以发现,如果我们把
考虑使用插值的方法求出这个多项式,这里采用傅里叶变换。我们做次数界次
可是中间的
时间复杂度
代码实现
#include <iostream>#include <cstring>#include <cstdio>using namespace std;const int P=998244353;const int N=2505;const int S=1<<3;const int L=8192;const int G=3;int bitcnt[8]={0,1,1,2,1,2,2,3};int omega[L+5],t[L+5],trs[L+5];int mat[3][3],tmp[3][3];bool legal[1<<6];int f[N][S];int a[L+5];int n,m,len,wn;struct matrix{ int num[S][S]; int r,c; matrix operator*(matrix const mat)const { matrix ret;ret.r=r,ret.c=mat.c,memset(ret.num,0,sizeof ret.num); for (int i=0;i<ret.r;++i) for (int j=0;j<ret.c;++j) for (int k=0;k<c;++k) (ret.num[i][j]+=1ll*num[i][k]*mat.num[k][j]%P)%=P; return ret; }}zero,one,F;matrix operator^(matrix x,int y){ matrix ret=zero; for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x; return ret;}int quick_power(int x,int y){ int ret=1; for (;y;y>>=1,x=1ll*x*x%P) if (y&1) ret=1ll*ret*x%P; return ret;}void DFT(int *a,int sig){ for (int i=0;i<len;++i) t[trs[i]]=a[i]; for (int l=2;l<=len;l<<=1) for (int h=l>>1,p=len/l,i=0;i<h;++i) for (int w=omega[sig>0?i*p:len-i*p],j=i;j<len;j+=l) { int u=t[j],v=1ll*t[j+h]*w%P; t[j]=(u+v)%P,t[j+h]=(u-v+P)%P; } for (int i=0;i<len;++i) a[i]=t[i];}void NTT_pre(){ for (len=1;len<=n*3;len<<=1); wn=quick_power(G,(P-1)/len),omega[0]=1; for (int i=1;i<=len;++i) omega[i]=1ll*omega[i-1]*wn%P; for (int i=0;i<len;++i) { int ret=0; for (int x=i,j=1;j<len;x>>=1,j<<=1) ret=(ret<<1)|(x&1); trs[i]=ret; }}void pre(){ for (int sta=0;sta<1<<6;++sta) { for (int s=sta,i=0;i<2;++i) for (int j=0;j<3;++j,s>>=1) tmp[i][j]=s&1; bool flag=1; for (int i=0;flag&&i<3;++i) for (int j=0;flag&&j<3;++j) if (tmp[i][j]) for (int x=0;flag&&x<3;++x) for (int y=0;flag&&y<3;++y) if (!(x==1&&y==1)&&mat[x][y]) { int u=x-1+i,v=y-1+j; if (u>=0&&u<3&&v>=0&&v<3&&tmp[u][v]) flag=0; } legal[sta]=flag; } zero.r=zero.c=S; for (int i=0;i<S;++i) zero.num[i][i]=1;}int dp(int w){ memset(f,0,sizeof f); int pw[4];pw[0]=1; for (int i=1;i<=3;++i) pw[i]=1ll*pw[i-1]*w%P; F.r=1,F.c=S,memset(F.num,0,sizeof F.num); for (int s=0;s<S;++s) (F.num[0][s]+=quick_power(w,bitcnt[s]))%=P; one.r=one.c=S,memset(one.num,0,sizeof one.num); for (int s=0;s<S;++s) for (int s_=0;s_<S;++s_) if (legal[s|(s_<<3)]) (one.num[s][s_]+=pw[bitcnt[s_]]%P)%=P; F=F*(one^(n-1)); int ret=0; for (int s=0;s<S;++s) (ret+=F.num[0][s])%=P; return ret;}int main(){ freopen("battle.in","r",stdin),freopen("battle.out","w",stdout); scanf("%d%d",&n,&m); if (m>3*n) printf("0\n"); { for (int i=0;i<3;++i) for (int j=0;j<3;++j) scanf("%d",&mat[i][j]); pre(),NTT_pre(); for (int i=0;i<len;++i) a[i]=dp(omega[i]); DFT(a,-1); for (int inv=quick_power(len,P-2),i=0;i<len;++i) a[i]=1ll*a[i]*inv%P; printf("%d\n",a[m]); } fclose(stdin),fclose(stdout); return 0;}
阅读全文
0 0
- [JZOJ5251]决战
- 【jzoj5251】【GDOI2018模拟8.11】【决战】【状态压缩动态规划】
- 决战
- 决战OCR
- 《决战犹马镇》
- 《决战帝国》
- 决战时刻
- 决战多线程
- bzoj3159: 决战
- bzoj3159: 决战
- BZOJ3159 决战
- 张无忌决战光明顶
- 决战72hours
- 决战上院之颠
- 《决战恶意代码〉赞
- 决战代言狗
- 决战十天
- 决战朝鲜 游戏攻略
- js开发通用的缓存SDK
- ViewPager滑动的使能设置
- 钻石继承和虚基类
- Java NIO 读取文件、写入文件、读取写入混合
- windy数 HYSBZ
- [JZOJ5251]决战
- Quartz类,库,笔记
- 机器学习算法总结--GBDT
- Java创建和解析Json数据方法(二)——org.json包的使用
- 检出的项目到了java Resources 里面
- 什么是类
- DPDK架构与特点
- 解决Java读取properties文件中文乱码的问题
- springboot日志切换