传送门


思路

真是非常套路的一道题……

考虑\(DP\):设\(f_n\)为\(n\)个积木能搭出的方案数,\(g_n\)为所有方案的高度之和。

容易得到转移方程:

\[\begin{align*}
&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\)。

由转移方程可以得到:

\[\frac{f_n}{n!}=[n=0]+\sum_{i=1}^n \frac{1}{i!} \frac{f_{n-i}}{(n-i)!}
\]

\[F(x)=\sum_n \frac{f_n}{n!} x^n\\
S(x)=\sum_{n=1}^{\infty} \frac{1}{n!} x^n
\]

则有

\[\begin{align*}
F(x)-1&=F(x)S(x)\\
F(x)&=\frac{1}{1-S(x)}
\end{align*}
\]

多项式求逆即可。

接下来是求\(g_n\)。

令\(t_n=f_n+g_n\),则有

\[\frac{g_n}{n!}=\sum_{i=1}^n \frac{1}{i!} \frac{t_{n-i}}{(n-i)!}
\]

\[\begin{align*}
&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)=S(x)T(x)=S(x)F(x)+S(x)G(x)\\
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}\)。


代码

  1. #include<bits/stdc++.h>
  2. namespace my_std{
  3. using namespace std;
  4. #define pii pair<int,int>
  5. #define fir first
  6. #define sec second
  7. #define MP make_pair
  8. #define rep(i,x,y) for (int i=(x);i<=(y);i++)
  9. #define drep(i,x,y) for (int i=(x);i>=(y);i--)
  10. #define go(x) for (int i=head[x];i;i=edge[i].nxt)
  11. #define sz 400404
  12. typedef long long ll;
  13. const ll mod=998244353;
  14. template<typename T>
  15. inline void read(T& t)
  16. {
  17. t=0;char f=0,ch=getchar();
  18. double d=0.1;
  19. while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
  20. while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
  21. if(ch=='.')
  22. {
  23. ch=getchar();
  24. while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();
  25. }
  26. t=(f?-t:t);
  27. }
  28. template<typename T,typename... Args>
  29. inline void read(T& t,Args&... args){read(t); read(args...);}
  30. void file()
  31. {
  32. #ifndef ONLINE_JUDGE
  33. freopen("a.txt","r",stdin);
  34. #endif
  35. }
  36. // 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;}
  37. }
  38. using namespace my_std;
  39. inline ll ksm(ll x,int y)
  40. {
  41. ll ret=1;
  42. for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;
  43. return ret;
  44. }
  45. ll inv(ll x){return ksm(x,mod-2);}
  46. int r[sz],limit;
  47. void NTT_init(int n)
  48. {
  49. limit=1;int l=-1;
  50. while (limit<=n+n) limit<<=1,++l;
  51. rep(i,0,limit-1) r[i]=(r[i>>1]>>1)|((i&1)<<l);
  52. }
  53. void NTT(ll *a,int type)
  54. {
  55. rep(i,0,limit-1) if (i<r[i]) swap(a[i],a[r[i]]);
  56. for (int mid=1;mid<limit;mid<<=1)
  57. {
  58. ll Wn=ksm(3,(mod-1)/mid>>1);if (type==-1) Wn=inv(Wn);
  59. for (int len=mid<<1,j=0;j<limit;j+=len)
  60. {
  61. ll w=1;
  62. for (int k=0;k<mid;k++,w=w*Wn%mod)
  63. {
  64. ll x=a[j+k],y=w*a[j+k+mid]%mod;
  65. a[j+k]=(x+y)%mod;a[j+k+mid]=(mod+x-y)%mod;
  66. }
  67. }
  68. }
  69. if (type==1) return;
  70. ll I=inv(limit);
  71. rep(i,0,limit-1) a[i]=a[i]*I%mod;
  72. }
  73. ll tmp1[sz],tmp2[sz];
  74. void PolyInv(ll *a,ll *f,int n)
  75. {
  76. if (n==1) return (void)(f[0]=inv(a[0]));
  77. int mid=(n+1)>>1;
  78. PolyInv(a,f,mid);
  79. NTT_init(n);
  80. rep(i,0,mid-1) tmp1[i]=f[i];
  81. rep(i,0,n-1) tmp2[i]=a[i];
  82. NTT(tmp1,1);NTT(tmp2,1);
  83. rep(i,0,limit-1) tmp1[i]=tmp1[i]*(mod+2-tmp1[i]*tmp2[i]%mod)%mod;
  84. NTT(tmp1,-1);
  85. rep(i,0,n-1) f[i]=tmp1[i];
  86. rep(i,0,limit-1) tmp1[i]=tmp2[i]=0;
  87. }
  88. ll fac[sz],_fac[sz];
  89. void init(){fac[0]=_fac[0]=1;rep(i,1,sz-1) _fac[i]=inv(fac[i]=fac[i-1]*i%mod);}
  90. ll f[sz],g[sz],s[sz];
  91. ll t1[sz],t2[sz],t3[sz],t4[sz];
  92. int main()
  93. {
  94. file();
  95. init();
  96. int n=1e5+5,T;
  97. rep(i,1,n) s[i]=mod-_fac[i];
  98. ++s[0];
  99. PolyInv(s,t1,n);
  100. rep(i,1,n) f[i]=t1[i];f[0]=1;
  101. rep(i,0,n) t2[i]=t3[i]=f[i];--t3[0];
  102. NTT_init(n);
  103. NTT(t2,1);NTT(t3,1);
  104. rep(i,0,limit-1) t4[i]=t2[i]*t3[i]%mod;
  105. NTT(t4,-1);
  106. rep(i,1,n) g[i]=t4[i];
  107. read(T);
  108. while (T--) read(n),printf("%lld\n",g[n]*inv(f[n])%mod);
  109. }

洛谷P5162 WD与积木 [DP,NTT]的更多相关文章

  1. 洛谷 P5162 WD与积木 解题报告

    P5162 WD与积木 题目背景 WD整日沉浸在积木中,无法自拔-- 题目描述 WD想买\(n\)块积木,商场中每块积木的高度都是\(1\),俯视图为正方形(边长不一定相同).由于一些特殊原因,商家会 ...

  2. 洛谷 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 ...

  3. 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)

    洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\)​​​​​.我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...

  4. 洛谷2344 奶牛抗议(DP+BIT+离散化)

    洛谷2344 奶牛抗议 本题地址:http://www.luogu.org/problem/show?pid=2344 题目背景 Generic Cow Protests, 2011 Feb 题目描述 ...

  5. Lightning Conductor 洛谷P3515 决策单调性优化DP

    遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...

  6. 洛谷P1541 乌龟棋(四维DP)

    To 洛谷.1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游 ...

  7. 【洛谷】P1052 过河【DP+路径压缩】

    P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙 ...

  8. 【题解】洛谷P1052 [NOIP2005TG] 过河(DP+离散化)

    题目来源:洛谷P1052 思路 一开始觉得是贪心 但是仔细一想不对 是DP 再仔细一看数据不对 有点大 如果直接存下的话 显然会炸 那么就需要考虑离散化 因为一步最大跳10格 那么我们考虑从1到10都 ...

  9. 洛谷1736(二维dp+预处理)

    洛谷1387的进阶版,但很像. 1387要求是“全为1的正方形”,取dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]))吧?这个有“只有对 ...

随机推荐

  1. crosstool-ng编译交叉工具链

    一.准备工作 1. 建立工作文件夹 2.下载crosstool-ng git clone https://github.com/crosstool-ng/crosstool-ng crosstool- ...

  2. AD软件使用心得

    1.在更新原理图之前一定要标记所有器件,否则无法生成PCB器件. 2.学会用sch list网表来批量修改器件名称 3.布线的面

  3. PHP设计——单例模式与工厂模式

    一.单例模式又称为职责模式,它用来在程序中创建一个单一功能的访问点,通俗地说就是实例化出来的对象是唯一的.所有的单例模式至少拥有以下三种公共元素:1. 它们必须拥有一个构造函数,并且必须被标记为pri ...

  4. oracle 窗口函数over

    select *,sum(字段) over()from table :--相加所有行这个字段的和 select max(字段1),over(partition by  字段2,字段3) from ta ...

  5. 1.3 第一个python程序

    使用Pycharm编写第一个python程序 1.打开 Pycharm,选择 Create New Project,创建一个新项目 2.选择Pure Python表示创建一个纯Python程序项目,  ...

  6. 关于reduce的参数问题

    ECMAScript 5还新增了两个缩小数组的方法: reduce() 和 reduceRight() .这两个方法都会迭代数组的所有项,然后构建一个最终返回的值.其中, reduce() 方法从数组 ...

  7. CSS公共清除浏览器默认样式

    /*Vue隐藏*/ [v-cloak] { display: none; } /*清除样式*/ body, ol, ul, dl, li, dt, dd, h1, h2, h3, h4, h5, h6 ...

  8. 架构学习之高性能NoSQL

    关于NoSQL,看过一张图,挺形象:“1970,We have no SQL”->“1980,Know SQL”->“2000,NoSQL”->“2005,Not only SQL” ...

  9. 接口转换 数据库列表的内容 显示在datagrid

    public class AddressConverter : IValueConverter { public object Convert(object value, Type targetTyp ...

  10. python使用PDB进行调试

    参考链接:https://www.cnblogs.com/xiaohai2003ly/p/8529472.html 调入包:import pdb 调试时的一些命令: (1)p  变量名:查看变量:(p ...