卷积形式dp的多项式求逆做法
时间:2020-09-16
本文章向大家介绍卷积形式dp的多项式求逆做法,主要包括卷积形式dp的多项式求逆做法使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
https://www.luogu.com.cn/problem/P4721
很多题的dp方程写出来后是这种形式
这种东西当然可以cdq分治FFT解决
但实际上做一些推导就可以只利用多项式求逆解决
这个递推式可以这么来看
fn表示 用一些长度为1...n-1的长条 来组成 一个长度为n的长条一共有多少种方案
其中长度为i的长条有gi种
把F和G写成母函数后
比较显然的是 F=1+G1+G2+G^3+....... = 1/(1-G)
多项式求逆即可
#include<bits/stdc++.h>
#define N 440000
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
#define ull unsigned long long
using namespace std;
inline int read()
{
char ch=0;
int x=0,flag=1;
while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
return x*flag;
}
const int h=3,mo=998244353;
int ksm(int x,int k)
{
int ans=1;
while(k){if(k&1)ans=1ll*ans*x%mo;k>>=1;x=1ll*x*x%mo;}
return ans;
}
int inv(int x){return ksm((x%mo+mo)%mo,mo-2);}
int rev[N];
void ntt(int *f,int n,int flag)
{
for(int i=0;i<n;i++)
{
rev[i]=(rev[i>>1]>>1)+(i&1)*(n>>1);
if(i<rev[i])swap(f[i],f[rev[i]]);
}
for(int k=2,kk=1;k<=n;k<<=1,kk<<=1)
{
int wn=ksm(h,(mo-1)/k);
if(flag==-1)wn=inv(wn);
for(int i=0;i<n;i+=k)
for(int j=0,w=1;j<kk;j++,w=1ll*w*wn%mo)
{
int t=1ll*w*f[i+j+kk]%mo;
f[i+j+kk]=(f[i+j]-t)%mo;
f[i+j]=(f[i+j]+t)%mo;
}
}
if(flag==-1)
{
int k=inv(n);
for(int i=0;i<n;i++)f[i]=(1ll*f[i]*k%mo+mo)%mo;
}
}
int a[N],b[N];
void poly_ml(int n)
{
ntt(a,n,+1);
for(int i=0;i<n;i++)a[i]=1ll*a[i]*a[i]%mo;
ntt(a,n,-1);
}
void poly_mul(int n)
{
ntt(a,n,+1);ntt(b,n,+1);
for(int i=0;i<n;i++)a[i]=1ll*a[i]*b[i]%mo;
ntt(a,n,-1);
}
int v[N],fv[N];
void poly_inv(int m)
{
int n=1;
for(int i=0;i<2*m;i++)v[i]=0;
while(n<2*m)
{
if(n==1){v[0]=inv(fv[0]);n<<=1;continue;}
for(int i=0;i<n;i++)a[i]=v[i],a[i+n]=0;poly_ml(2*n);
for(int i=0;i<n;i++)b[i]=fv[i],a[i+n]=b[i+n]=0;poly_mul(2*n);
for(int i=0;i<n;i++)v[i]=(1ll*2*v[i]%mo-a[i])%mo,v[i+n]=0;
n<<=1;
}
}
int main()
{
int n=read();
for(int i=1;i<n;i++)fv[i]=((-read())%mo+mo)%mo;
fv[0]=1;poly_inv(n);printf("1 ");
for(int i=1;i<n;i++)printf("%d ",(v[i]%mo+mo)%mo);
return 0;
}
原文地址:https://www.cnblogs.com/Creed-qwq/p/13680197.html
- 【Code】关关的刷题日记21——Leetcode 485. Max Consecutive Ones
- 2017 Multi-University Training Contest - Team 9 1002&&HDU 6162 Ch’s gift【树链部分+线段树】
- 【Java学习笔记之三十二】浅谈Java中throw与throws的用法及异常抛出处理机制剖析
- Linux上访问SQL Server数据库
- 2017 Multi-University Training Contest - Team 9 1001&&HDU 6161 Big binary tree【树形dp+hash】
- 【Java学习笔记之三十三】详解Java中try,catch,finally的用法及分析
- 【Java学习笔记之二十九】Java中的"equals"和"=="的用法及区别
- NET跨平台:在Ubuntu下搭建ASP.NET 5开发环境
- 【Code】关关的刷题日记22——Leetcode 53. Maximum Subarray
- 【Java学习笔记之三十四】超详解Java多线程基础
- Codeforces 842B Gleb And Pizza【几何,水】
- Python3希尔排序
- Codeforces 842A Kirill And The Game【暴力,水】
- Wannafly模拟赛 A.矩阵(二分答案+hash)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【程序源代码】基于Python开发的Markdown在线文档系统
- 深度学习Pytorch检测实战 - Notes - 第4章 两阶经典检测器:Faster RCNN
- Numpy中的两个乱序函数
- PerfDog4.0探索,支持用户自建web云
- 跨帐号访问COS资源
- 聊聊dubbo-go的DubboProtocol
- 推荐一个很牛叉的开源Flask项目
- 机器学习应用资产管理系列一:强化学习策略(附代码)
- 3分钟短文 | Laravel模型关联删除表记录,用观察者还是事件钩子
- 原理+代码|深入浅出Python随机森林预测实战
- 3分钟短文 | Laravel复杂SQL超多WHERE子句,本地作用域你没用过
- 3分钟短文 | Laravel同时连接多个数据库,你用啥办法?
- 3分钟短文 | PHP 连接2个字符串的8个方法,新手常犯错
- nodejs源码分析之connect
- 你应该了解的Nacos配置中心