多项式快速幂(加强版)

这篇具有很好参考价值的文章主要介绍了多项式快速幂(加强版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

建议阅读我的上一篇博客多项式快速幂

求多项式快速幂,但 a 0 ≠ 1 a_0\not=1 a0=1

由于求 ln ⁡ \ln ln 要求 a 0 = 1 a_0=1 a0=1,所以我们要想办法对多项式进行变换,使其满足 a 0 = 1 a_0=1 a0=1

如果 f ( x ) f(x) f(x) 常数项为 0 0 0,那么就整体除去 x x x 的若干次方,使常数项为 0 0 0

然后再对每项系数除以常数项,这样 a 0 a_0 a0 就等于 1 1 1 了。求法见我上一篇博客。

求出结果后,记得还原回去。

设原函数为 f ( x ) f(x) f(x),变换后的函数为 g ( x ) g(x) g(x),则 f ( x ) k = s k x t k g ( x ) k f(x)^k=s^kx^{tk}g(x)^k f(x)k=skxtkg(x)k s s s f ( x ) f(x) f(x) 从小到大第一个非零系数, t t t 是那一项的次数。

如果 t k ≥ n tk\ge n tkn,答案就是 0 0 0

s k s^k sk 可使用扩展欧拉定理, s k ≡ s k   m o d   φ ( p ) ( m o d p ) s^k\equiv s^{k\bmod \varphi(p)}\pmod p skskmodφ(p)(modp)

参考代码如下文章来源地址https://www.toymoban.com/news/detail-468663.html

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=(1<<18)+1;
const ll mod=998244353,g=3,inv2=499122177;
int len=1,n;
ll a1[N],w,wn,a[N],ans[N],invans[N],lnans[N],da[N],inva[N],a2[N];
char s[N];
ll ksm(ll a,ll b)
{
    ll ans=1;
    while(b){
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
void change(ll num[])
{
    for(int i=1,j=len/2;i<len-1;i++){
        if(i<j) swap(num[i],num[j]);
        int k=len/2;
        while(j>=k) j-=k,k>>=1;
        if(j<k) j+=k;
    }
}
void ntt(ll num[],int fl)
{
    for(int i=2;i<=len;i<<=1){
        if(fl==1) wn=ksm(g,(mod-1)/i);
        else wn=ksm(g,mod-1-(mod-1)/i);
        for(int j=0;j<len;j+=i){
            w=1;
            for(int k=j;k<j+i/2;k++){
                ll u=w*num[k+i/2]%mod,t=num[k];
                num[k]=(t+u)%mod;
                num[k+i/2]=(t-u+mod)%mod;
                w=w*wn%mod;
            }
        }
    }
    if(fl==-1){
        ll inv=ksm(len,mod-2);
        for(int i=0;i<len;i++) num[i]=num[i]*inv%mod;
    }
}
void getinv(int n,ll a[],ll ans[])
{
	if(n==1){ans[0]=ksm(a[0],mod-2);return;}
	getinv((n+1)/2,a,ans);
	len=1;
	while(len<2*n) len*=2;
	for(int i=0;i<n;i++) a1[i]=a[i];
	for(int i=n;i<len;i++) a1[i]=0;
	change(a1),change(ans);
	ntt(a1,1),ntt(ans,1);
	for(int i=0;i<len;i++) ans[i]=ans[i]*(2-ans[i]*a1[i]%mod+mod)%mod;
	change(ans),ntt(ans,-1);
	for(int i=n;i<len;i++) ans[i]=0;
}
void getln(int n,ll a[],ll ln[])
{
    memset(da,0,sizeof(da));
	for(int i=1;i<n;i++) da[i-1]=a[i]*i%mod;
    da[n-1]=0;
    memset(inva,0,sizeof(inva));
	getinv(n,a,inva);
	len=1;
	while(len<2*n) len*=2;
	change(da),change(inva);
	ntt(da,1),ntt(inva,1);
	for(int i=0;i<len;i++) ln[i]=da[i]*inva[i]%mod;
	change(ln),ntt(ln,-1);
	for(int i=len-1;i>=0;i--) ln[i+1]=ksm(i+1,mod-2)*ln[i]%mod;
    for(int i=n;i<len;i++) ln[i]=0;
	ln[0]=0;
}
void getsqrt(int n,ll a[],ll ans[])
{
    if(n==1){ans[0]=a[0];return;}
    getsqrt((n+1)/2,a,ans);
    len=1;
    while(len<2*n) len*=2;
    memset(invans,0,sizeof(invans));
    getinv(n,ans,invans);
    for(int i=0;i<n;i++) a1[i]=a[i];
    for(int i=n;i<len;i++) a1[i]=0;
    change(a1),change(invans);
    ntt(a1,1),ntt(invans,1);
    for(int i=0;i<len;i++) a1[i]=a1[i]*invans[i]%mod;
    change(a1),ntt(a1,-1);
    for(int i=0;i<n;i++) ans[i]=(a1[i]+ans[i])*inv2%mod;
    for(int i=n;i<len;i++) ans[i]=0;
}
void getexp(int n,ll a[],ll ans[])
{
    if(n==1){ans[0]=1;return;}
    getexp((n+1)/2,a,ans);
    len=1;
    while(len<2*n) len*=2;
    memset(lnans,0,sizeof(lnans));
    getln(n,ans,lnans);
    for(int i=0;i<n;i++) lnans[i]=(-lnans[i]+a[i]+mod)%mod;
    lnans[0]++;
    change(ans),change(lnans);
    ntt(ans,1),ntt(lnans,1);
    for(int i=0;i<len;i++) ans[i]=ans[i]*lnans[i]%mod;
    change(ans),ntt(ans,-1);
    for(int i=n;i<len;i++) ans[i]=0;
}
void getksm(int n,ll a[],char *s,ll ans[])
{
    ll k1=0,k2=0;
    int len=strlen(s);
    for(int i=0;i<len;i++) k1=(k1*10+s[i]-48)%mod,k2=(k2*10+s[i]-48)%(mod-1);
    ll x=0;
    while(x<n&&!a[x]) x++;
    if(x&&len>=6||k1*x>=n){
        memset(ans,0,sizeof(ans));
        return;
    }
    for(int i=0;i<n-x;i++) a[i]=a[i+x];
    for(int i=n-x;i<n;i++) a[i]=0;
    ll a0=a[0],y=ksm(a0,mod-2);
    for(int i=0;i<n-x*k1;i++) a[i]=a[i]*y%mod;
    getln(n-x*k1,a,a2);
    for(int i=0;i<n-x*k1;i++) a2[i]=a2[i]*k1%mod;
    getexp(n-x*k1,a2,ans);
    y=ksm(a0,k2);
    for(int i=n-1;i>=x*k1;i--) ans[i]=ans[i-x*k1]*y%mod;
    for(int i=0;i<x*k1;i++) ans[i]=0;
}
int main()
{
	scanf("%d%s",&n,s);
	for(int i=0;i<n;i++) scanf("%lld",&a[i]);
    getksm(n,a,s,ans);
    for(int i=0;i<n;i++) printf("%lld ",ans[i]);
}

到了这里,关于多项式快速幂(加强版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C 数据结构】 用单链表存储一元多项式,并实现两个多项式相加运算。

    本次代码纯c语言,可以支持输入两个多项式的项式、系数、指数。 实验目的: 1 掌握单链表的基本工作原理; 2 实现链式存储下的两个多项式的相加。 实验步骤 1 定义链式存储的数据结构 2 完成多项式的初始化,即给多项式赋初值 3 完成多项式的输出 4 实现多项式的相加及结

    2024年02月06日
    浏览(37)
  • 基于MATLAB的矩阵性质:行列式,秩,迹,范数,特征多项式与矩阵多项式

    本节主要讨论矩阵的基本概念和性质,结合MATLAB的基础代码,适合新手。 矩阵的 行列式 的数学定义如下: MATLAB调用的格式如下: 求以下矩阵的行列式: 解: MATLAB代码如下: 运行结果: ans =    5.1337e-13 利用解析解的方法计算20✖️20的Hilbert矩阵的行列式,并分析其代码运

    2024年02月05日
    浏览(47)
  • 牛顿插值法、拉格朗日插值法、三次插值、牛顿插值多项式、拉格朗日插值多项式

    两点式线性插值 调用Matlab库函数 拉格朗日二次插值: 牛顿二次插值 结果分析:通过对比不同插值方法,可以看到在一定范围内(高次会出现龙格现象),插值次数越高,截断误差越小(插值结果越接近于真实函数值);同时,对于相同次数的插值,由于不同的插值方法它们

    2024年02月11日
    浏览(36)
  • 多项式混沌展开法

    多项式混沌采用多项式基组合成随机空间,来描述和传播随机变量的不确定性。本质是利用正交多项式的优异性能,通过随机变量的输入到响应的映射过程建立代理模型。该方法收敛性好,使用方便,能较好的适用于复杂的系统。但是该方法理论难度高,多元情况下正交多项

    2023年04月15日
    浏览(33)
  • Matlab 多项式拟合

    corrcoef函数 corrcoef函数用来计算矩阵相关系数。 (1)、corrcoef(x):若x为一个矩阵,返回的则是一个相关系数矩阵。 (2)、corrcoef(x,y):计算列向量x、y的相关系数,要求x、y具有相等的元素个数。如果x、y是矩阵,那么corrcoef函数会将其转换为列向量,相当于corrcoef([x(:),y(:)])。   p

    2024年02月11日
    浏览(37)
  • 多项式拟合

    文章内容部分参考: 建模算法入门笔记-多项式拟合(附源码) - 哔哩哔哩 (bilibili.com) (9条消息) 数学建模——人口预测模型 公有木兮木恋白的博客-CSDN博客 数学建模人口预测模型 多项式拟合是数据拟合的一种,与插值有一定区别(插值要求曲线经过给定的点,拟合不一定经

    2024年02月04日
    浏览(36)
  • Jacobi正交多项式

    注:本文的内容主要根据文末中的参考文档[1,2,3]中的内容进行整理完成。 设 I = [ − 1 , 1 ] I=[-1,1] I = [ − 1 , 1 ] 是实轴上的标准区间,定义在 I I I 上的正函数: ω α , β ( x ) = ( 1 − x ) α ( 1 + x ) β , α − 1 , β − 1 omega_{alpha,beta}(x)=(1-x)^{alpha}(1+x)^{beta}, alpha-1,beta-1 ω α , β

    2024年02月13日
    浏览(34)
  • 多项式承诺:KZG

    参考文献: Merkle, R. ”Protocols for Public Key Cryptosystems.” Proc. 1980 Symp. on Security and Privacy, IEEE Computer Society (April 1980), 122-133. Benaloh J, Mare M. One-way accumulators: A decentralized alternative to digital signatures[C]//Workshop on the Theory and Application of of Cryptographic Techniques. Springer, Berlin, Heidelberg, 1993

    2024年02月04日
    浏览(45)
  • 多项式乘法逆

    前置知识:NTT学习笔记(快速数论变换) 情景代入 洛谷P4238 【模板】多项式乘法逆 给定一个多项式 f ( x ) f(x) f ( x ) ,求 g ( x ) g(x) g ( x ) ,满足 f ( x ) × g ( x ) ≡ 1 ( m o d x n ) f(x)times g(x)equiv 1pmod{x^n} f ( x ) × g ( x ) ≡ 1 ( mod x n ) 。系数对 998244353 998244353 998244353 取模。 1 ≤

    2024年02月02日
    浏览(37)
  • Matlab作图多项式拟合

    一、拟合函数 polyfit(s,y,n) polyval(p,x) poly2str(p,\\\' x \\\' ) 二、拟合步骤 1.做原始数据的散点图 2.选择恰当的次数n,用polyfit指令求得多项式 3.计算多项式p在x处的值 4.画出多项式函数的曲线图 三、拟合实例 对x等于1-10,y大于20小于40的随机数进行多项式拟合 x=1:10;y=20+20*rand(1,10);%定义

    2023年04月25日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包