【洛谷P5158】 【模板】多项式快速插值
卡常严重,可有采用如下优化方案:
1.预处理单位根
2.少取几次模
3.复制数组时用 memcpy
4.进行多项式乘法项数少的时候直接暴力乘
5.进行多项式多点求值时如果项数小于500的话直接秦九昭展开
code:
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define setIO(s) freopen(s".in","r",stdin) // , freopen(s".out","w",stdout)
using namespace std;
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd()
{
int x=0; char s=nc();
while(s<'0') s=nc();
while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
return x;
}
void print(int x) {if(x>=10) print(x/10);putchar(x%10+'0');}
const int G=3;
const int N=2000005;
const int mod=998244353;
int A[N],B[N],w[2][N],mem[N*100],*ptr=mem;
inline int qpow(int x,int y)
{
int tmp=1;
for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) tmp=(ll)tmp*x%mod;
return tmp;
}
inline int INV(int a) { return qpow(a,mod-2); }
inline void ntt_init(int len)
{
int i,j,k,mid,x,y;
w[1][0]=w[0][0]=1,x=qpow(3,(mod-1)/len),y=qpow(x,mod-2);
for (i=1;i<len;++i) w[0][i]=(ll)w[0][i-1]*x%mod,w[1][i]=(ll)w[1][i-1]*y%mod;
}
void NTT(int *a,int len,int flag)
{
int i,j,k,mid,x,y;
for(i=k=0;i<len;++i)
{
if(i>k) swap(a[i],a[k]);
for(j=len>>1;(k^=j)<j;j>>=1);
}
for(mid=1;mid<len;mid<<=1)
for(i=0;i<len;i+=mid<<1)
for(j=0;j<mid;++j)
{
x=a[i+j], y=(ll)w[flag==-1][len/(mid<<1)*j]*a[i+j+mid]%mod;
a[i+j]=(x+y)%mod;
a[i+j+mid]=(x-y+mod)%mod;
}
if(flag==-1)
{
int rev=INV(len);
for(i=0;i<len;++i) a[i]=(ll)a[i]*rev%mod;
}
}
inline void getinv(int *a,int *b,int len,int la)
{
if(len==1) { b[0]=INV(a[0]); return; }
getinv(a,b,len>>1,la);
int l=len<<1,i;
memset(A,0,l*sizeof(A[0]));
memset(B,0,l*sizeof(A[0]));
memcpy(A,a,min(la,len)*sizeof(a[0]));
memcpy(B,b,len*sizeof(b[0]));
ntt_init(l);
NTT(A,l,1),NTT(B,l,1);
for(i=0;i<l;++i) A[i]=((ll)2-(ll)A[i]*B[i]%mod+mod)*B[i]%mod;
NTT(A,l,-1);
memcpy(b,A,len<<2);
}
struct poly
{
int len,*a;
poly(){}
poly(int l) {len=l,a=ptr,ptr+=l; }
inline void rev() { reverse(a,a+len); }
inline void fix(int l) {len=l,a=ptr,ptr+=l;}
inline void get_mod(int l) { for(int i=l;i<len;++i) a[i]=0; len=l; }
inline poly dao()
{
poly re(len-1);
for(int i=1;i<len;++i) re.a[i-1]=(ll)i*a[i]%mod;
return re;
}
inline poly Inv(int l)
{
poly b(l);
getinv(a,b.a,l,len);
return b;
}
inline poly operator * (const poly &b) const
{
poly c(len+b.len-1);
if(c.len<=500)
{
for(int i=0;i<len;++i)
if(a[i]) for(int j=0;j<b.len;++j) c.a[i+j]=(c.a[i+j]+(ll)(a[i])*b.a[j])%mod;
return c;
}
int n=1;
while(n<(len+b.len)) n<<=1;
memset(A,0,n<<2);
memset(B,0,n<<2);
memcpy(A,a,len<<2);
memcpy(B,b.a,b.len<<2);
ntt_init(n);
NTT(A,n,1), NTT(B,n,1);
for(int i=0;i<n;++i) A[i]=(ll)A[i]*B[i]%mod;
NTT(A,n,-1);
memcpy(c.a,A,c.len<<2);
return c;
}
poly operator + (const poly &b) const
{
poly c(max(len,b.len));
for(int i=0;i<c.len;++i) c.a[i]=((i<len?a[i]:0)+(i<b.len?b.a[i]:0))%mod;
return c;
}
poly operator - (const poly &b) const
{
poly c(len);
for(int i=0;i<len;++i)
{
if(i>=b.len) c.a[i]=a[i];
else c.a[i]=(a[i]-b.a[i]+mod)%mod;
}
return c;
}
poly operator / (poly u)
{
int n=len,m=u.len,l=1;
while(l<(n-m+1)) l<<=1;
rev(),u.rev();
poly v=u.Inv(l);
v.get_mod(n-m+1);
poly re=(*this)*v;
rev(),u.rev();
re.get_mod(n-m+1);
re.rev();
return re;
}
poly operator % (poly u)
{
poly re=(*this)-u*(*this/u);
re.get_mod(u.len-1);
return re;
}
}p[N<<2],pr;
int xx[N],yy[N];
#define lson now<<1
#define rson now<<1|1
inline void pushup(int l,int r,int now)
{
int mid=(l+r)>>1;
if(r>mid) p[now]=p[lson]*p[rson];
else p[now]=p[lson];
}
void build(int l,int r,int now,int *pp)
{
if(l==r)
{
p[now].fix(2);
p[now].a[0]=mod-pp[l];
p[now].a[1]=1;
return;
}
int mid=(l+r)>>1;
if(l<=mid) build(l,mid,lson,pp);
if(r>mid) build(mid+1,r,rson,pp);
p[now]=p[lson]*p[rson];
}
void get_val(int l,int r,int now,poly b,int *pp,int *t)
{
if(b.len<=500)
{
for(int i=l;i<=r;++i)
{
ull s=0;
for(int j=b.len-1;j>=0;--j)
{
s=((ull)s*pp[i]+b.a[j])%mod;
if(!(j&7)) s%=mod;
}
t[i]=s%mod;
}
return;
}
int mid=(l+r)>>1;
if(l<=mid) get_val(l,mid,lson,b%p[lson],pp,t);
if(r>mid) get_val(mid+1,r,rson,b%p[rson],pp,t);
}
poly solve_polate(int l,int r,int now,int *t)
{
if(l==r)
{
poly re(1);
re.a[0]=t[l];
return re;
}
int mid=(l+r)>>1;
poly L,R;
L=solve_polate(l,mid,lson,t);
R=solve_polate(mid+1,r,rson,t);
return L*p[rson]+R*p[lson];
}
void check_Interpolate();
poly Interpolate(int *a,int *b,int n);
void check_Evaluation();
void check_Inv();
void check_mult();
void check_divide();
poly Interpolate(int *a,int *b,int n)
{
int i,j;
build(1,n,1,a);
static int t[N];
poly tmp=p[1].dao();
get_val(1,n,1,tmp,a,t);
for(i=1;i<=n;++i) t[i]=(ll)INV(t[i])*b[i]%mod;
return solve_polate(1,n,1,t);
}
void check_Interpolate()
{
// setIO("input");
int i,j,n;
n=rd();
for(i=1;i<=n;++i) xx[i]=rd(),yy[i]=rd();
poly re=Interpolate(xx,yy,n);
for(i=0;i<re.len;++i) print(re.a[i]), printf(" ");
for(;i<n;++i) print(re.a[i]), printf(" ");
}
void check_Evaluation()
{
int i,j,n,m,l;
n=rd(),m=rd();
pr.fix(n+1);
static int pp[N];
for(i=0;i<=n;++i) pr.a[i]=rd();
for(i=1;i<=m;++i) pp[i]=rd();
build(1,m,1,pp);
get_val(1,m,1,pr,pp,pp);
for(i=1;i<=m;++i) printf("%d\n",pp[i]);
}
void check_Inv()
{
int i,j,n;
scanf("%d",&n);
pr.fix(n);
for(i=0;i<n;++i) scanf("%d",&pr.a[i]);
int l=1;
while(l<n) l<<=1;
pr=pr.Inv(l);
for(i=0;i<n;++i) printf("%d ",pr.a[i]);
}
void check_mult()
{
int i,j,n,m;
scanf("%d%d",&n,&m);
poly a(n+1),b(m+1);
for(i=0;i<=n;++i) scanf("%d",&a.a[i]);
for(i=0;i<=m;++i) scanf("%d",&b.a[i]);
a=a*b;
for(i=0;i<a.len;++i) printf("%d ",a.a[i]);
}
void check_divide()
{
int i,j,n,m;
scanf("%d%d",&n,&m);
poly F(n+1), G(m+1);
for(i=0;i<=n;++i) scanf("%d",&F.a[i]);
for(i=0;i<=m;++i) scanf("%d",&G.a[i]);
poly Q=F/G;
poly R=F%G;
for(i=0;i<Q.len;++i) printf("%d ",Q.a[i]);
printf("\n");
for(i=0;i<R.len;++i) printf("%d ",R.a[i]);
}
【洛谷P5158】 【模板】多项式快速插值的更多相关文章
- 洛谷.3803.[模板]多项式乘法(FFT)
题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. 5.4 又看了一遍,这个也不错. 2019.3.7 叕看了一遍,推荐这个. #inclu ...
- 洛谷.3803.[模板]多项式乘法(NTT)
题目链接:洛谷.LOJ. 为什么和那些差那么多啊.. 在这里记一下原根 Definition 阶 若\(a,p\)互质,且\(p>1\),我们称使\(a^n\equiv 1\ (mod\ p)\ ...
- 洛谷.4512.[模板]多项式除法(NTT)
题目链接 多项式除法 & 取模 很神奇,记录一下. 只是主要部分,更详细的和其它内容看这吧. 给定一个\(n\)次多项式\(A(x)\)和\(m\)次多项式\(D(x)\),求\(deg(Q) ...
- 洛谷.4238.[模板]多项式求逆(NTT)
题目链接 设多项式\(f(x)\)在模\(x^n\)下的逆元为\(g(x)\) \[f(x)g(x)\equiv 1\ (mod\ x^n)\] \[f(x)g(x)-1\equiv 0\ (mod\ ...
- 洛谷 P4512 [模板] 多项式除法
题目:https://www.luogu.org/problemnew/show/P4512 看博客:https://www.cnblogs.com/owenyu/p/6724611.html htt ...
- 洛谷 P4238 [模板] 多项式求逆
题目:https://www.luogu.org/problemnew/show/P4238 看博客:https://www.cnblogs.com/xiefengze1/p/9107752.html ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 多项式求逆元详解+模板 【洛谷P4238】多项式求逆
概述 多项式求逆元是一个非常重要的知识点,许多多项式操作都需要用到该算法,包括多项式取模,除法,开跟,求ln,求exp,快速幂.用快速傅里叶变换和倍增法可以在$O(n log n)$的时间复杂度下求出 ...
- 洛谷P3375 [模板]KMP字符串匹配
To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
随机推荐
- Django开发简单博客流程
什么是Django? Django是一个基于python的高级web开发框架 它能够让开发人员进行高效且快速的开发 高度集成(不用自己造轮子), 免费并且开源 当前路径创建工程 django-admi ...
- springboot 通过@WebFilter(urlPatterns )配置Filter过滤路径
springboot 通过@WebFilter(urlPatterns )配置Filter过滤路径,没有配置/*,输入任何路径都能进过滤器 2019年04月25日 12:51:33 peigui.hu ...
- (转)微服务_创建一个简单的Eureka注册中心
原文地址:https://www.cnblogs.com/lplshermie/p/9105329.html 微服务和分布式已经成了一种极其普遍的技术,为了跟上时代的步伐,最近开始着手学习Spring ...
- Java8新特性:接口
Java接口本身没有任何实现,因为Java接口不涉及表象,而只描述public行为,所以Java接口比Java抽象类更抽象化. 以上是百度百科中对接口的定义,这个定义已经不准确. Java8对接口做了 ...
- 【转载】C#中List集合使用IndexOf判断元素第一次出现的索引位置
在C#的List集合操作中,有时候需要判断元素对象在List集合中第一次出现的索引位置信息,此时需要使用到List集合的IndexOf方法来判断,如果元素存在List集合中,则IndexOf方法返回所 ...
- HttpClient使用详解与实战一:普通的GET和POST请求
简介 HttpClient是Apache Jakarta Common下的子项目,用来提供高效的.最新的.功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议. Htt ...
- Java 初始化块
初始化块是和成员变量.成员函数一个级别的.一般用于类的初始化,也可执行其他java代码,作用和构造函数相同. 创建对象时,初始化块在构造函数之前执行. 初始化块分为普通初始化块.静态初始化块. 普通初 ...
- Ubuntu16.04 网络配置
Ubuntu 网络配置 安装Ubuntu操作系统之后,为了通过Xshell连接主机,或者连接其他主机.需要进行如下网络配置和ssh服务配置. 1 网络配置 1.1 修改网络配置信息 sudo vi / ...
- Linux加密和数据安全性
加密和安全 墨菲定律 墨菲定律:一种心理学效应,是由爱德华·墨菲(Edward A. Murphy)提出的, 原话:如果有两种或两种以上的方式去做某件事情,而其中一种选择方式将导 致灾难,则必定有人会 ...
- 【HICP Gauss】数据库 数据库管理(文件 用户管理 系统权限 对象权限 profile)-7
数据库运行 依赖不同类型的文件 ,数据文件 参数文件 控制文件 redo日志文件 运行日志文件 审计日志文件等 数据文件 就是表空间文件 存储数据库的数据文件 参数文件 用户修改的配置信息 控制文件 ...