博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【XSY2730】Ball 多项式exp 多项式ln 多项式开根 常系数线性递推 DP
阅读量:4624 次
发布时间:2019-06-09

本文共 2709 字,大约阅读时间需要 9 分钟。

题目大意

  一行有\(n\)个球,现在将这些球分成\(k\) 组,每组可以有一个球或相邻两个球。一个球只能在至多一个组中(可以不在任何组中)。求对于\(1\leq k\leq m\)的所有\(k\)分别有多少种分组方法。

  答案对\(998244353\)取模。

  \(n\leq {10}^9,m<2^{19}\)

题解

  因为\(k>n\)的项都是\(0\),所以我们钦定\(m\leq n\)

  考虑DP。

  记\(f_{i,j}\)为前\(i\)个球分为\(j\)组的方案数。

\[ f_{i,j}=f_{i-1,j}+f_{i-1,j-1}+f_{i-2,j-1} \]
  直接做是\(O(nm)\)的。

  如果把\(f_i\)看成一个多项式,即

\[ F_i(x)=\sum_{j\geq 0}f_{i,j}x^j \]
  那么转移就变成了
\[ F_i(x)=(1+x)F_{i-1}(x)+xF_{i-2}(x) \]
  这是一个常系数齐次线性递推,用FFT优化可以做到\(O(m\log m\log n)\)

  考虑怎么求一个常系数齐次线性递推关系的通项公式。

  先求出这个转移矩阵的特征多项式:

\[ \lambda^2-(1+x)\lambda-x \]
  特征值为
\[ \begin{align} \lambda_1&=\frac{1+x+\sqrt{x^2+6x+1}}{2}\\ \lambda_2&=\frac{1+x-\sqrt{x^2+6x+1}}{2} \end{align} \]
  我们钦定\(F_{-1}(x)=0\),设
\[ F_i(x)=c_1{\lambda_1}^{i+1}+c_2{\lambda_2}^{i+1} \]
  带入\(F_{-1}(x),F_0(x)\)
\[ \begin{cases} c_1&+c2&=0\\ c_2\lambda_1&+c_2\lambda_2&=1 \end{cases} \]
  解得
\[ \begin{cases} c_1&=\frac{1}{\lambda_1-\lambda_2}\\ c_2&=\frac{1}{\lambda_2-\lambda_1} \end{cases} \]
  于是
\[ F_i(x)=\frac{
{\lambda_1}^{i+1}-{\lambda_2}^{i+1}}{\lambda_1-\lambda_2} \]
  直接用多项式开根求出\(\lambda_1,\lambda_2\),然后用多项式\(\ln \exp\)求出\(F_n(x)\)

  时间复杂度:\(O(m\log m)\)

  小优化:因为\([x^0]\lambda_2=0\),所以\(\lambda_2\)的前\(n+1\)项都是\(0\)。因为\(m\leq n\),所以

\[ {\lambda_2}^{n+1}\equiv 0 \pmod {x^{m+1}} \]
  所以我们不用计算\({\lambda_2}^{n+1}\)了。

代码

#include
#include
#include
using namespace std;typedef long long ll;const int maxn=300000;const ll p=998244353;const ll g=3;const ll inv2=(p+1)/2;ll fp(ll a,ll b){ ll s=1; for(;b;b>>=1,a=a*a%p) if(b&1) s=s*a%p; return s;}int rev[maxn];ll w1[maxn];ll w2[maxn];void ntt(ll *a,int n,int t){ int i,j,k; ll u,v,w,wn; for(i=1;i
>1]>>1)|(i&1?n>>1:0); if(rev[i]>i) swap(a[i],a[rev[i]]); } for(i=2;i<=n;i<<=1) { wn=(t==1?w1[i]:w2[i]); for(j=0;j
>1); static ll a1[maxn],a2[maxn]; int i; for(i=0;i
>1;i++) a2[i]=b[i]; for(;i
<<1;i++) a2[i]=0; ntt(a1,n<<1,1); ntt(a2,n<<1,1); for(i=0;i
<<1;i++) a1[i]=a2[i]*((2-a1[i]*a2[i])%p)%p; ntt(a1,n<<1,-1); for(i=0;i
>1); static ll a1[maxn],a2[maxn],a3[maxn]; int i; for(i=0;i
>1;i++) a1[i]=b[i]; for(;i
<<1;i++) a1[i]=0; for(i=0;i
>1); int i; for(i=n>>1;i
>1;i++) { a2[i]=b[i]; a3[i]=a[i+(n>>1)]-a1[i+(n>>1)]; } for(;i
>1;i++) b[i+(n>>1)]=a2[i];}ll a[maxn];ll b[maxn];ll c[maxn];ll d[maxn];ll e[maxn];int n,m;int k;void solve(){ k=1; while(k<=m) k<<=1; int i; for(i=2;i<=k<<1;i++) { w1[i]=fp(g,(p-1)/i); w2[i]=fp(w1[i],p-2); } d[0]=1; d[1]=6; d[2]=1; getsqrt(d,c,k); for(i=0;i
n) { x=m-n; m=n; } solve(); while(x--) printf("0 "); return 0;}

转载于:https://www.cnblogs.com/ywwyww/p/8513484.html

你可能感兴趣的文章
ArcPy开发教程2-管理地图文档1
查看>>
过滤器的使用
查看>>
ES6快到碗里来---一个简单的爬虫指南
查看>>
Spring mvc源码url路由-我们到底能走多远系列(38)
查看>>
2018.3.28 学了点cmake和makefile
查看>>
无法启动程序baseclasses.lib
查看>>
Who Am I? Personality Detection based on Deep Learning for Texts 阅读笔记
查看>>
sublime 主要使用方法
查看>>
Dictionary、SortedDictionary、Hashtable 、SortedList使用条件小结
查看>>
Wormholes
查看>>
根据类名获取元素
查看>>
下拉框
查看>>
我在百度开放云编程马拉松上的一个创意
查看>>
拼出漂亮的表格
查看>>
Java(四、类和对象)
查看>>
结对第一次—原型设计(文献摘要热词统计)
查看>>
echarts + timeline 显示多个options
查看>>
springmvc+quartz简单实现定时调度
查看>>
CentOS下递归遍历文件夹下所有文件,查找指定字符
查看>>
[PHP]利用XAMPP搭建本地服务器, 然后利用iOS客户端上传数据到本地服务器中(一.安装XAMPP)...
查看>>