洛谷P5162 WD与积木 [DP,NTT]
思路
真是非常套路的一道题……
考虑\(DP\):设\(f_n\)为\(n\)个积木能搭出的方案数,\(g_n\)为所有方案的高度之和。
容易得到转移方程:
&f_n=[n=0]+\sum_{i=1}^n {n \choose i} f_{n-i}\\
&g_n=\sum_{i=1}^n {n \choose i} (f_{n-i}+g_{n-i})
\end{align*}
\]
发现\(f_n\)似乎更容易搞出来,我们先搞\(f_n\)。
由转移方程可以得到:
\]
设
S(x)=\sum_{n=1}^{\infty} \frac{1}{n!} x^n
\]
则有
F(x)-1&=F(x)S(x)\\
F(x)&=\frac{1}{1-S(x)}
\end{align*}
\]
多项式求逆即可。
接下来是求\(g_n\)。
令\(t_n=f_n+g_n\),则有
\]
设
&G(x)=\sum_n \frac{g_n}{n!} x^n\\
&T(x)=\sum_n \frac{t_n}{n!}=F(x)+G(x)
\end{align*}
\]
可以得到
G(x)=\frac{S(x)F(x)}{1-S(x)}=S(x)[F(x)]^2=F(x)(F(x)-1)
\]
NTT即可。
最后\(ans_n=\frac{g_n}{f_n}\)。
代码
#include<bits/stdc++.h>
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define sz 400404
typedef long long ll;
const ll mod=998244353;
template<typename T>
inline void read(T& t)
{
t=0;char f=0,ch=getchar();
double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.')
{
ch=getchar();
while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();
}
t=(f?-t:t);
}
template<typename T,typename... Args>
inline void read(T& t,Args&... args){read(t); read(args...);}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.txt","r",stdin);
#endif
}
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
inline ll ksm(ll x,int y)
{
ll ret=1;
for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;
return ret;
}
ll inv(ll x){return ksm(x,mod-2);}
int r[sz],limit;
void NTT_init(int n)
{
limit=1;int l=-1;
while (limit<=n+n) limit<<=1,++l;
rep(i,0,limit-1) r[i]=(r[i>>1]>>1)|((i&1)<<l);
}
void NTT(ll *a,int type)
{
rep(i,0,limit-1) if (i<r[i]) swap(a[i],a[r[i]]);
for (int mid=1;mid<limit;mid<<=1)
{
ll Wn=ksm(3,(mod-1)/mid>>1);if (type==-1) Wn=inv(Wn);
for (int len=mid<<1,j=0;j<limit;j+=len)
{
ll w=1;
for (int k=0;k<mid;k++,w=w*Wn%mod)
{
ll x=a[j+k],y=w*a[j+k+mid]%mod;
a[j+k]=(x+y)%mod;a[j+k+mid]=(mod+x-y)%mod;
}
}
}
if (type==1) return;
ll I=inv(limit);
rep(i,0,limit-1) a[i]=a[i]*I%mod;
}
ll tmp1[sz],tmp2[sz];
void PolyInv(ll *a,ll *f,int n)
{
if (n==1) return (void)(f[0]=inv(a[0]));
int mid=(n+1)>>1;
PolyInv(a,f,mid);
NTT_init(n);
rep(i,0,mid-1) tmp1[i]=f[i];
rep(i,0,n-1) tmp2[i]=a[i];
NTT(tmp1,1);NTT(tmp2,1);
rep(i,0,limit-1) tmp1[i]=tmp1[i]*(mod+2-tmp1[i]*tmp2[i]%mod)%mod;
NTT(tmp1,-1);
rep(i,0,n-1) f[i]=tmp1[i];
rep(i,0,limit-1) tmp1[i]=tmp2[i]=0;
}
ll fac[sz],_fac[sz];
void init(){fac[0]=_fac[0]=1;rep(i,1,sz-1) _fac[i]=inv(fac[i]=fac[i-1]*i%mod);}
ll f[sz],g[sz],s[sz];
ll t1[sz],t2[sz],t3[sz],t4[sz];
int main()
{
file();
init();
int n=1e5+5,T;
rep(i,1,n) s[i]=mod-_fac[i];
++s[0];
PolyInv(s,t1,n);
rep(i,1,n) f[i]=t1[i];f[0]=1;
rep(i,0,n) t2[i]=t3[i]=f[i];--t3[0];
NTT_init(n);
NTT(t2,1);NTT(t3,1);
rep(i,0,limit-1) t4[i]=t2[i]*t3[i]%mod;
NTT(t4,-1);
rep(i,1,n) g[i]=t4[i];
read(T);
while (T--) read(n),printf("%lld\n",g[n]*inv(f[n])%mod);
}
洛谷P5162 WD与积木 [DP,NTT]的更多相关文章
- 洛谷 P5162 WD与积木 解题报告
P5162 WD与积木 题目背景 WD整日沉浸在积木中,无法自拔-- 题目描述 WD想买\(n\)块积木,商场中每块积木的高度都是\(1\),俯视图为正方形(边长不一定相同).由于一些特殊原因,商家会 ...
- 洛谷 P5162 WD与积木【多项式求逆】
设f[i]为i个积木能堆出来的种类,g[i]为i个积木能堆出来的种类和 \[ f[n]=\sum_{i=1}^{n}C_{n}^{i}g[n-i] \] \[ g[n]=\sum_{i=1}^{n}C ...
- 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)
洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\).我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...
- 洛谷2344 奶牛抗议(DP+BIT+离散化)
洛谷2344 奶牛抗议 本题地址:http://www.luogu.org/problem/show?pid=2344 题目背景 Generic Cow Protests, 2011 Feb 题目描述 ...
- Lightning Conductor 洛谷P3515 决策单调性优化DP
遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...
- 洛谷P1541 乌龟棋(四维DP)
To 洛谷.1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游 ...
- 【洛谷】P1052 过河【DP+路径压缩】
P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙 ...
- 【题解】洛谷P1052 [NOIP2005TG] 过河(DP+离散化)
题目来源:洛谷P1052 思路 一开始觉得是贪心 但是仔细一想不对 是DP 再仔细一看数据不对 有点大 如果直接存下的话 显然会炸 那么就需要考虑离散化 因为一步最大跳10格 那么我们考虑从1到10都 ...
- 洛谷1736(二维dp+预处理)
洛谷1387的进阶版,但很像. 1387要求是“全为1的正方形”,取dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]))吧?这个有“只有对 ...
随机推荐
- Your accoutn already has a valid IOS Distribution certificate
这个问题是IOS证书不对,登录Apple开发中心,清空所有证书,然后再Archive->Reset.
- ubuntu没有/usr/include/sys目录
实际上不是没有sys目录,只是系统给换路径了 32位系统:/usr/incude/i386-linux-gnu/sys 64位系统:/usr/include/x86_64-linux-gnu/sys/ ...
- 六、文件IO——fcntl 函数 和 ioctl 函数
6.1 fcntl 函数 6.1.1 函数介绍 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd ...
- javascript 正则表达式总结
为什么要使用正则表达式 正则表达式通过由普通字符和特殊字符组成的文字模板完成对字符串的校验,搜索,替换.在javascript中类似这样 /^1\d{10}$/ 复制代码 上面的这个简单的正则用来匹配 ...
- 【Django】git建仓上传时遇到的小问题
根据教程 http://tutorial.djangogirls.org/zh/deploy/,在github上建仓上传项目文件. 执行到 git push -u origin master 时,输入 ...
- [C++]常识回顾
1.基本/常用数据类型及其取值范围 类型标识 名称 占用字节数(位数) 取值范围 bool 逻辑型 1(1) 常量true或者false char 字符型 1(8) [2^7, 2^7 - 1] 或者 ...
- 2017CCPC秦皇岛 A题Balloon Robot&&ZOJ3981【模拟】
题意: 一个机器人在长为M的圆形轨道上送气球,当机器人到达M号点的时候下一站会回到1号点,且全程不会停止运动.现在在长为M的轨道上有N个队伍,队伍会在某个时间做需要一个气球,机器人需要送过去.一共有P ...
- python 关于文件操作
,要求在文件 .py 第六行插入一句话: #cat /root/python/2.py 2 昨夜雨疏风骤1 3 昨夜雨疏风骤2 4 昨夜雨疏风骤3 5 昨夜雨疏风骤4 6 昨夜雨疏风骤5 7 昨夜雨疏 ...
- js 中编码(encode)和解码(decode)的三种方法
js对文字进行编码涉及3个函数:escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decodeURIComponent 下 ...
- Flume配置Failover Sink Processor
1 官网内容 2 看一张图一目了然 3 详细配置 source配置文件 #配置文件: a1.sources= r1 a1.sinks= k1 k2 a1.channels= c1 #负载平衡 a1.s ...