[JZOJ5364]史莱姆
题目大意
给你一个棱长为 2n 2^n的正方体,你可以进行m次攻击,求攻击完后正方体样子的方案数。
一次攻击定义为:你对一个棱长为 2i 2^i的正方体进行分解,分解成8个 2i−1 2^{i-1}次方个小正方体。
两种方案不同定义为:存在一对棱长为1的正方体单位x,y,在一种方案中他们属于同一个正方体而另一种方案他们属于不同正方体。
多组数据。
T≤100000,n≤40,m≤30000。
分析
一个小DP:
设f[i][j][k]表示考虑到大小为 2n−i 2^{n-i}的大小的正方体,比他大的正方体一共用了j次攻击,当前大小的正方体有8*k个,的方案数。
很显然 f[i][j][k]=∑f[i+1][j−k][l]∗c(k,l∗8) f[i][j][k]=\sum{f[i+1][j-k][l]*c(k,l*8)}
这就是部分分了。
这东西没办法优化了,我们要换个思路。
看到统计方案的题,想想生成函数总是没问题的,首先要推出一个能够搞生成函数的dp。
我们反过来,合成一个 2n 2^n的正方体。
设f[i][j]表示一个 2i 2^i的正方体,用j次攻击的方案数,转移式是:
f[i][j]=∑a[1..8]|sum(a)=j−1(f[i−1][a[1]]∗⋅⋅⋅f[i−1][a[8]]) f[i][j]=\sum_{a[1..8]|sum(a)=j-1}(f[i-1][a[1]]*···f[i-1][a[8]]),即枚举攻击一次后分解成的8个小正方体的分割情况。特别的,f[i][0]=1。
现在我们把f(i)看成一个多项式,f[i][j]表示f[i]的第j项的系数,就可以FFT了!
f(i)=f(i−1)8∗x+1 f(i)=f(i-1)^8*x+1,那么只要对f(i-1)求幂,然后整体右移一位,再令常数项+1,就是f(i)了。把答案记录下来直接输出即可。
这个NTT有大半年没打···低级错误犯了好多,回顾一下。
len为原多项式次数界之和,再调整到2^x。
递归过程中:对n次多项式带入 w1n,w2n...wnn w_n^1,w_n^2...w_n^n
我们DFT的过程中,求
t[i]=a[0],a[1]∗win,a[2]∗w2in... t[i]=a[0],a[1]*w_n^i,a[2]*w_n^{2i}...
t[i+n/2]=a[0],a[1]∗wi+n/2n,a[2]∗wi+nn... t[i+n/2]=a[0],a[1]*w_n^{i+n/2},a[2]*w_n^{i+n}...
i∈[0,len−1] i\in[0,len-1]
对t[i]分析,分组转化得
(a[0],a[2]∗win/2,a[4]∗w2in/2) (a[0],a[2]*w_{n/2}^{i},a[4]*w_{n/2}^{2i})
win∗(a[1],a[3]∗win/2,a[5]∗w2in/2) w_n^i*(a[1],a[3]*w_{n/2}^{i},a[5]*w_{n/2}^{2i})
括号里的东西分别储存在 t′[i],t′[i+n/2] t'[i],t'[i+n/2]中。
t[i]=t′[i]+t′[i+n/2]∗win t[i]=t'[i]+t'[i+n/2]*w_n^i
t[i+n/2]=t′[i]+t′[i+n/2]∗wi+n/2n=t′[i]+t′[i+n/2]∗w−in t[i+n/2]=t'[i]+t'[i+n/2]*w_n^{i+n/2}=t'[i]+t'[i+n/2]*w_n^{-i}
二进制表示的下标中,a为dft目标数组,t为过程数组, t[0101]=a[1010] t[0101]=a[1010]
dft后,两个数组相乘,所有的点值都要乘,不然插值会出错。
插值就把 wlen−i w_len^{-i}带入,最后出来的多项式系数要除以len。
预处理原根下的那些主次方根。
代码
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
using namespace std;
#define fo(i,j,k) for(i=j;i<=k;i++)
#define fd(i,j,k) for(i=j;i>=k;i--)
typedef long long ll;
typedef double db;
const int N=1e5+5,mo=998244353,rt=3;
int Log,w[N],len,n,m,T,i,f[42][N],g[N],a[N],invl,j,k;
int t[N];
struct rec
{int n,m,id;
}b[N];
int ksm(int x,int y)
{int ret=1;while (y){if (y&1) ret=1ll*ret*x%mo;y>>=1;x=1ll*x*x%mo;}return ret;
}
int mx2(int x)
{int ret=1;Log=0;while (ret<x) ret*=2,Log++;return ret;
}
void predo()
{int i;w[0]=1;w[1]=ksm(rt,(mo-1)/len);fo(i,2,len) w[i]=1ll*w[i-1]*w[1]%mo;
}
void DFT(int *a,int n,int sig)
{int i,j,ws,half,siz,k,pos,u,v;fo(i,0,n-1){int tp=0;fo(j,0,Log-1) tp=(tp<<1)+(((1<<j)&i)!=0);t[tp]=a[i];}for(ws=1,siz=2;siz<=n;siz*=2,ws++){half=siz>>1;fo(i,0,half-1){for(j=i;j<n;j+=siz){k=j+half;pos=len/siz*i*sig;if (pos<0) pos+=len;u=t[j];v=1ll*t[k]*w[pos]%mo;t[j]=(u+v)%mo;t[k]=(u-v+mo)%mo;}}}fo(i,0,n-1) a[i]=t[i];
}
int main()
{scanf("%d\n",&T);fo(i,1,T){scanf("%d %d",&b[i].n,&b[i].m);n=max(n,b[i].n);m=max(m,b[i].m);b[i].id=i;}f[0][0]=1;len=mx2(m*2+2);invl=ksm(len,mo-2);predo();fo(i,1,n){fo(j,0,m) g[j]=f[i-1][j];fo(j,1,3){fo(k,0,m) a[k]=g[k];DFT(a,len,1);fo(k,0,len-1) a[k]=1ll*a[k]*a[k]%mo;DFT(a,len,-1);fo(k,0,m) g[k]=1ll*a[k]*invl%mo;fo(k,0,len-1) a[k]=0;}fo(j,1,m) f[i][j]=g[j-1];f[i][0]=1;}fo(i,1,T) printf("%d\n",f[b[i].n][b[i].m]);
}
[JZOJ5364]史莱姆相关推荐
- 中石油训练赛 - 关于我转生变成史莱姆这档事(dfs)
题目描述 关于我转生变成史莱姆这档事这部番剧中,上班族的三上悟因为某个事件而作为史莱姆在异世界转生了.在转生时得到了"大贤者"和"捕食者"这两个独特技能.虽然身 ...
- coreldraw登录老是出现未知错误_原神:新版本bug频出,史莱姆消失,联机模式提示506错误码...
这个1.1版本真就"乐事"不断呀,各种bug频出,冻梨有些疑惑,版本上线前真的经过测试了么?不会就开发组跑一遍正常流程,通了就急匆匆地更新了吧. 绝大部分玩家都遭遇了的506错误代 ...
- android模拟器 diy,史莱姆机DIY模拟器
史莱姆机DIY模拟器是一款非常治愈减压的手机游戏.该游戏有很多乐趣,它的玩法就类似与橡皮泥的玩法,不断你怎么捏它都是一个形状,该有戏是一款粘液模拟器,你可以在游戏里捏出各种各样的DIY出来,游戏画面和 ...
- 分裂的史莱姆(二进制)
Description 史莱姆(Slime),是一种在现代电子游戏与奇幻小说常常出现的虚构生物,最早在1958年同名小说里出现.其流行形象是一种果冻状或半液体状.身体不透明或半透明.可以变换形状.能够 ...
- 史莱姆区块查找 超简单java代码
现有的史莱姆区块查找器 打不开史莱姆区块查找器,自己写一个算了 步骤: 1.新建一个txt文件,复制下面代码到文件里并保存,然后文件名连同后缀改为 McCheckSlimeChunk.java 2.打 ...
- Java练习ArrayList的运用——勇者斗史莱姆
现在有五个角色:勇者.法师.骑士.史莱姆.哥布林,他们各自具有的属性为姓名(name).生命值(health).基础攻击力(ATK). 首先,我们需要创建一个角色类(Role),为了方便日后查询角色状 ...
- 你听说过史莱姆吗??【oj】
Description Input Output inpu 5 output 1 input 8 output 0 分析: 如果只有小Q一个人的话,就会有1,2,4,8,16,32,,,等情况,是以二 ...
- 基本算法的设计与实现-史莱姆通话
题目描述 有n只史莱姆在数轴上站成一列,距离小于等于K的两只史莱姆之间可以相互通话.请问有多少对史莱姆之间能通话? 输入 两行,第一行,两个整数n和K,其中n<=500: 第二行,一个长度为n的 ...
- 史莱姆方块java_史莱姆 - Minecraft Wiki,最详细的官方我的世界百科
史莱姆 大型:16( × 8) 中型:4( ) 小型:1() 行为 攻击型 攻击力 简单: 大型:3( ) 中型:2() 小型:0() 普通: 大型: 4( ) 中型: 2() 小型: 0() 困难: ...
最新文章
- Vxworks信号量分析
- 理解一下select 1 和 exists
- mysql基础命令大全
- 微软MCP之SharePoint2007考试试题(Microsoft 70-542)
- 连续3年入围 Gartner 容器竞争格局,阿里云容器服务新布局首次公开
- Eclipse调试Java的10个技巧
- pdf.js跨域加载文件
- 《JavaScript 学习指南》
- 数据结构队列的代码实现
- 使用accton进行进程会计处理
- Vmware虚拟机ikuai路由配置
- 当你觉得焦虑,烦躁的时候怎么办?
- MiniGPT4,开源了
- [linux-023]在thinkpad T480上安装ubuntu 20.04 LTS
- f4ck论坛的小游戏(灌水贴)
- sublimelinter java_学习使用sublime插件sublimeLinter
- 浦东街镇医保卡制卡网点地址电话
- arm汇编的学习笔记,对比x86和arm(1)-从最简单的函数谈起
- 北京工业大学2019年第八届暑期科技夏令营全记录 (计算机专业)
- OPPO R9m怎么刷机 OPPO R9m的刷机教程 OPPO R9m完美解除账号锁