题面

传送门

前置芝士

\(MTT\),多项式多点求值

题解

这题法老当初好像讲过……而且他还说这种题目如果模数已经给定可以直接分段打表艹过去

以下是题解

我们设

\[F(x)=\prod_{i=0}^{s-1}(x+i)\]

分治\(FFT\)即可求出

然后我们用多点求值求出\(x=1,s+1,2s+1,...,s^2-s+1\)时的答案

这样的话可以计算出\((s^2)!\),剩下没计算的部分直接暴力就是了

如果我们取\(s=\sqrt{n}\),复杂度大概就是\(O(s\log^2s)\)

以下是吐槽

啊……模数任意……没事把以前代码里都换成\(MTT\)就可以了

信心满满交上去发现只有\(40\)分

模数\(2e9\)?那两个数加起来都得爆\(int\)了啊……再改改……

交上去还是只有\(40\)分

突然想起来正常\(MTT\)的时候是取\(2^{15}\)的,然而这里值域可以达到\(2^{31}\),还是要炸啊……那么改成\(2^{16}\)好了

还是\(40\)分……

最后再仔细看了看,因为我多点求值的写法中最后小的部分是直接暴力秦九韶循环展开的,然后,四个\(p\times p\)级别的数加起来炸\(long\ long\)了……

强制定义一个\(__int128\)类型的\(0\)加上去……

终于\(A\)了……

ps:建议交之前测一下一下这组数据

\(p=2^{31}-1,n=p-1\),根据威尔逊定理有\(n!\equiv -1\pmod{p}\)

可以看看你到底炸了没有

upd:被\(shadowice\)巨巨的倍增吊打了QAQ(虽然也能\(A\)就是了),倍增的做法看这里(不知道比多点求值高到哪里去了)

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define III __int128
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int N=(1<<17)+5;const double Pi=acos(-1.0);
int P;III zero;
inline int add(R int x,R int y){return 1ll*x+y>=P?1ll*x+y-P:x+y;}
inline int dec(R int x,R int y){return 1ll*x-y<0?1ll*x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){R int res=1;for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;return res;
}
struct cp{double x,y;cp(){}cp(R double xx,R double yy):x(xx),y(yy){}inline cp operator +(const cp &b)const{return cp(x+b.x,y+b.y);}inline cp operator -(const cp &b)const{return cp(x-b.x,y-b.y);}inline cp operator *(const cp &b)const{return cp(x*b.x-y*b.y,x*b.y+y*b.x);}inline cp operator *(const double &b)const{return cp(x*b,y*b);}inline cp operator ~()const{return cp(x,-y);}
}w[2][N];
int r[21][N],lg[N];double inv[21];
void Pre(){fp(d,0,17){fp(i,1,(1<<d)-1)r[d][i]=(r[d][i>>1]>>1)|((i&1)<<(d-1));lg[1<<d]=d,inv[d]=1.0/(1<<d);}for(R int i=1,d=0;i<131072;i<<=1,++d)fp(k,0,i-1){w[1][i+k]=cp(cos(Pi*k*inv[d]),sin(Pi*k*inv[d])),w[0][i+k]=cp(cos(Pi*k*inv[d]),-sin(Pi*k*inv[d]));}
}
int lim,d;
void FFT(cp *A,int ty){fp(i,0,lim-1)if(i<r[d][i])swap(A[i],A[r[d][i]]);cp t;for(R int mid=1;mid<lim;mid<<=1)for(R int j=0;j<lim;j+=(mid<<1))fp(k,0,mid-1)A[j+k+mid]=A[j+k]-(t=A[j+k+mid]*w[ty][mid+k]),A[j+k]=A[j+k]+t;if(!ty)fp(i,0,lim-1)A[i]=A[i]*inv[d];
}
void MTT(int *a,int *b,int len,int *c){static cp f[N],g[N],p[N],q[N];lim=(len<<1),d=lg[lim];fp(i,0,len-1)f[i]=cp(a[i]>>15,a[i]&32767),g[i]=cp(b[i]>>15,b[i]&32767);fp(i,len,lim-1)f[i]=g[i]=cp(0,0);FFT(f,1),FFT(g,1);fp(i,0,lim-1){cp t,f0,f1,g0,g1;t=~f[i?lim-i:0],f0=(f[i]-t)*cp(0,-0.5),f1=(f[i]+t)*0.5;t=~g[i?lim-i:0],g0=(g[i]-t)*cp(0,-0.5),g1=(g[i]+t)*0.5;p[i]=f1*g1,q[i]=f1*g0+f0*g1+f0*g0*cp(0,1);}FFT(p,0),FFT(q,0);fp(i,0,lim-1)c[i]=(((ll)(p[i].x+0.5)%P<<30)+((ll)(q[i].x+0.5)<<15)+((ll)(q[i].y+0.5)))%P;
}
void Inv(int *a,int *b,int len){if(len==1)return b[0]=ksm(a[0],P-2),void();Inv(a,b,len>>1);static int c[N],d[N];MTT(a,b,len,c),MTT(c,b,len,d);fp(i,0,len-1)b[i]=dec(add(b[i],b[i]),d[i]);
}
struct node{node *lc,*rc;vector<int>vec;int deg;void Mod(const int *a,int *r,int n){static int A[N],B[N],D[N];int len=1;while(len<=n-deg)len<<=1;fp(i,0,n)A[i]=a[n-i];fp(i,0,deg)B[i]=vec[deg-i];fp(i,n-deg+1,len-1)B[i]=0;Inv(B,D,len);fp(i,n-deg+1,len-1)A[i]=D[i]=0;MTT(A,D,len,A);reverse(A,A+n-deg+1);len=1;while(len<=max(n-deg,deg))len<<=1;fp(i,0,deg)B[i]=vec[i];fp(i,deg+1,len-1)B[i]=0;fp(i,n-deg+1,len-1)A[i]=0;MTT(A,B,len,A);fp(i,0,deg-1)r[i]=dec(a[i],A[i]);}void Mul(){static int A[N],B[N];deg=lc->deg+rc->deg,vec.resize(deg+1);int len=1;while(len<=max(lc->deg,rc->deg))len<<=1;fp(i,0,lc->deg)A[i]=lc->vec[i];fp(i,lc->deg+1,len-1)A[i]=0;fp(i,0,rc->deg)B[i]=rc->vec[i];fp(i,rc->deg+1,len-1)B[i]=0;MTT(A,B,len,A);fp(i,0,deg)vec[i]=A[i];}
}pool[N<<1],*rt,*qwq,*pp=pool;
int A[N],a[N];
void solve(node* &p,int l,int r){p=pp++;if(l==r)return p->deg=1,p->vec.resize(2),p->vec[0]=a[l],p->vec[1]=1,void();int mid=(l+r)>>1;solve(p->lc,l,mid),solve(p->rc,mid+1,r);p->Mul();
}
int b[25],res;
void calc(node *p,int l,int r,const int *A){if(r-l<=512){fp(i,l,r){int x=a[i],c1,c2,c3,c4,now=A[r-l];b[0]=1;fp(j,1,16)b[j]=mul(b[j-1],x);for(R int j=r-l-1;j-15>=0;j-=16){c1=(zero+1ll*now*b[16]+1ll*A[j]*b[15]+1ll*A[j-1]*b[14]+1ll*A[j-2]*b[13])%P,c2=(zero+1ll*A[j-3]*b[12]+1ll*A[j-4]*b[11]+1ll*A[j-5]*b[10]+1ll*A[j-6]*b[9])%P,c3=(zero+1ll*A[j-7]*b[8]+1ll*A[j-8]*b[7]+1ll*A[j-9]*b[6]+1ll*A[j-10]*b[5])%P,c4=(zero+1ll*A[j-11]*b[4]+1ll*A[j-12]*b[3]+1ll*A[j-13]*b[2]+1ll*A[j-14]*b[1])%P,now=(0ll+c1+c2+c3+c4+A[j-15])%P;}fd(j,(r-l)%16-1,0)now=(1ll*now*x+A[j])%P;res=mul(res,now);}return;}int mid=(l+r)>>1,b[p->deg+1];p->lc->Mod(A,b,p->deg-1),calc(p->lc,l,mid,b);p->rc->Mod(A,b,p->deg-1),calc(p->rc,mid+1,r,b);
}
int n,s;
int main(){
//  freopen("testdata.in","r",stdin);scanf("%d%d",&n,&P),res=1,s=sqrt(n),Pre(),zero=0;fp(i,1,s)a[i]=i-1;solve(qwq,1,s);fp(i,1,s)a[i]=P-((i-1)*s+1);solve(rt,1,s);fp(i,0,s)A[i]=qwq->vec[i];rt->Mod(A,A,s);fp(i,1,s)a[i]=(i-1)*s+1;calc(rt,1,s,A);fp(i,s*s+1,n)res=mul(res,i);printf("%d\n",res);return 0;
}

转载于:https://www.cnblogs.com/bztMinamoto/p/10646575.html

洛谷P5282 【模板】快速阶乘算法(多项式多点求值+MTT)相关推荐

  1. [2021CCPC 威海G] Shinyruo and KFC (下降幂多项式乘法+下降幂转普通幂+多项式多点求值)

    题意 给定 n n n 个正整数 a 1 , a 2 , ⋯ , a n a_1,a_2,\cdots,a_n a1​,a2​,⋯,an​,并给定正整数 m m m,对于每个 k ∈ [ 1 , m ...

  2. 多项式多点求值与快速插值

    考虑给定多项式fff,如何求f(x1),f(x2),f(x3),...,f(xn)f(x_1),f(x_2),f(x_3),...,f_(x_n)f(x1​),f(x2​),f(x3​),...,f( ...

  3. 洛谷P5050 【模板】多项式多点求值

    传送门 人傻常数大.jpg 因为求逆的时候没清零结果调了几个小时-- 前置芝士 多项式除法,多项式求逆 什么?你不会?左转你谷模板区,包教包会 题解 首先我们要知道一个结论\[f(x_0)\equiv ...

  4. 255.0.0.0子网掩码相应的cidr前缀表示法是?_【洛谷日报#246】浅谈表达式的求值(Vol.2 进阶)...

    Warning 在观看本博客之前,请保证自己理解了表达式的三种表达方式. 本文旨在让大家更深层次的了解表达式,基础的知识就是上方的链接中所写的.所以,在了解后缀表达式的运算原理之后,我将不会讲述类似的 ...

  5. 多项式的求逆、取模和多点求值学习小记

    最近学习了多项式的求逆.取模和多点求值,这些方法能够解决很多多项式问题. 这三个操作是环环相扣的,很有趣,学完后不妨记录一下. 多项式求逆 给出一个次数界为 nnn 的多项式 A(x)A(x)A(x) ...

  6. 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)

    预备知识:FFT/NTT 多项式的逆 给定一个多项式 F(x)F(x)F(x),请求出一个多项式 G(x)G(x)G(x),满足 F(x)∗G(x)≡1(modxn)F(x)*G(x) \equiv ...

  7. 洛谷or牛客数据结构+算法

    栈思想:先进后出 tips:栈里能放下标就放下标 (牛客)小c的计事本(直接用stack可以简化代码,且不会被自己绕晕,当时没意识到) (牛客)吐泡泡(没意识到用栈),(牛客)好串 1.后缀表达式(栈 ...

  8. @总结 - 4@ 多项式的多点求值与快速插值

    目录 @0 - 参考资料@ @1 - 多点求值@ @理论推导@ @参考代码@ @例题与应用@ @2 - 快速插值@ @理论推导@ @(不建议参考的)代码@ @例题与应用@(暂无) @0 - 参考资料@ ...

  9. matlab二元多项式求值,matlab多项式代入求值

    Matlab 多项式运算与方程求根 ? Matlab多项式运算无论是在线性代数中,还是信号处理.自动控制等理论 中,多项式运算都有着十分重要的地位,因此,MATLAB 为多项式的操作提供了相应的函数库 ...

最新文章

  1. SSH框架中 Spring设置定时器 Quartz
  2. Swift - UITableView状态切换效果
  3. C语言三剑客之《C陷阱与缺陷》一书精华提炼
  4. 如何画正太分布曲线_python scipy.stats实现各种常见的统计分布
  5. vs中opencv配置
  6. wordpress邮件地址混淆 你没权限访问整个邮件地址造成的死链接
  7. HDFS的StartupProgress启动跟踪分析
  8. 正面管教php_我就这样走进正面管教
  9. java基础(三):java面向对象OOP
  10. 使用树莓派搭建直播平台实现b站实时直播
  11. CSTC 2017 要匙
  12. ssh免密码登录快速配置方法
  13. MySQL processlist的state属性详解
  14. 【题目】NKOJ-4247 老蒋的数列
  15. Avro技术应用_5. 利用 Camus 来将 Avro 数据从 Kafka 拷贝到 HDFS -- 待完善
  16. fastadmin创蓝短信插件第二版
  17. 当了10年程序员,我开窍了!
  18. 西瓜书学习笔记——第一、二章
  19. pdf学习资源整理(c++ opencv 深度学习等等)
  20. Windows Style Builder颜色模块的ColorizationColor值问题

热门文章

  1. phpexcel删除行_在PHPexcel中删除空行
  2. python抽取某个时间段的数据_python 批量提取excel 指定时间段的数据
  3. java中break和continue的用法
  4. 关于continue用法总结
  5. 二阶魔方复原算法推算-Part2
  6. 华盛顿大学计算机科学,华盛顿大学计算机科学与信息系统Computer Science and Information Systems世界排名2020年最新排名第18位(QS世界排名)...
  7. Axure交互模拟线框图等等
  8. PAZU WEB打印控件
  9. 计算机在开机后显示器在显示桌面,电脑开机后显示器黄灯怎么办
  10. 云队友丨追求复利人生,升级思维模型的四个层级