zoukankan      html  css  js  c++  java
  • 洛谷P5245 【模板】多项式快速幂

    https://www.luogu.org/problemnew/show/P5245(常数项保证为1)

    https://www.luogu.org/problemnew/show/U63679   https://www.luogu.org/problemnew/show/P5273(常数项无限制,幂次<模数)

    方法:$a^b=(e^{ln(a)})^b=e^{ln(a)b}$,多项式ln要求a的常数项为1,当a常数项为1时,这个过程可以直接对模数(998244353)取模(我不知道具体为什么)

    因此如果a的常数项为0,就“右移”直到常数项非0(设右移了k位),快速幂完了“左移”回去(要左移bk位)

    (如果所有项都是0,那么快速幂之后答案一定仍为0,特判掉就好)

    如果常数项已经非0了但不是1,那么设常数项为k,$a^b=(frac{a}{k}k)^b=(frac{a}{k})^bk^b$,做法就是先所有项除以常数项,然后快速幂,最后所有项乘上$k^b$(注意最后这一步b如果要取模,就要对(phi(模数))(998244352)取模)

    版本1:基于版本2,一般要求输入函数的b就是原始的b,没有取过模

      1 #prag
      2 ma GCC optimize(2)
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<vector>
      7 #include<cmath>
      8 using namespace std;
      9 #define fi first
     10 #define se second
     11 #define mp make_pair
     12 #define pb push_back
     13 typedef long long ll;
     14 typedef unsigned long long ull;
     15 const int md=998244353;
     16 const int N=262144;
     17 #define delto(a,b) ((a)-=(b),((a)<0)&&((a)+=md))
     18 inline int del(int a,int b)
     19 {
     20     a-=b;
     21     return a<0?a+md:a;
     22 }
     23 int rev[N];
     24 void init(int len)
     25 {
     26     int bit=0,i;
     27     while((1<<(bit+1))<=len)    ++bit;
     28     for(i=1;i<len;++i)
     29         rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
     30 }
     31 ull poww(ull a,ull b)
     32 {
     33     ull ans=1;
     34     for(;b;b>>=1,a=a*a%md)
     35         if(b&1)
     36             ans=ans*a%md;
     37     return ans;
     38 }
     39 int inv[300011];
     40 void dft(int *a,int len,int idx)//要求len为2的幂
     41 {
     42     int i,j,k,t1,t2;ull wn,wnk;
     43     for(i=0;i<len;++i)
     44         if(i<rev[i])
     45             swap(a[i],a[rev[i]]);
     46     for(i=1;i<len;i<<=1)
     47     {
     48         wn=poww(idx==1?3:332748118,(md-1)/(i<<1));
     49         for(j=0;j<len;j+=(i<<1))
     50         {
     51             wnk=1;
     52             for(k=j;k<j+i;++k,wnk=wnk*wn%md)
     53             {
     54                 t1=a[k];t2=a[k+i]*wnk%md;
     55                 a[k]+=t2;
     56                 (a[k]>=md)&&(a[k]-=md);
     57                 a[k+i]=t1-t2;
     58                 (a[k+i]<0)&&(a[k+i]+=md);
     59             }
     60         }
     61     }
     62     if(idx==-1)
     63     {
     64         ull ilen=inv[len];
     65         for(i=0;i<len;++i)
     66             a[i]=a[i]*ilen%md;
     67     }
     68 }
     69 void p_inv(int *f,int *g,int len)//g=f^(-1);f,g数组的长度不小于2len(需要足够长用于临时存放元素);要求len是2的幂
     70 {
     71     static int t1[N],t2[N];
     72     g[0]=poww(f[0],md-2);
     73     for(int i=2,j;i<=len;i<<=1)
     74     {
     75         memcpy(t1,f,sizeof(int)*i);
     76         memcpy(t2,g,sizeof(int)*(i>>1));
     77         memset(t2+(i>>1),0,sizeof(int)*(i>>1));
     78         init(i);
     79         dft(t1,i,1);dft(t2,i,1);
     80         for(j=0;j<i;++j)
     81             t1[j]=ull(t1[j])*t2[j]%md;
     82         dft(t1,i,-1);
     83         for(j=0;j<(i>>1);++j)
     84             t1[j]=t1[j+(i>>1)];
     85         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
     86         dft(t1,i,1);
     87         for(j=0;j<i;++j)
     88             t1[j]=ull(t1[j])*t2[j]%md;
     89         dft(t1,i,-1);
     90         for(j=i>>1;j<i;++j)
     91             g[j]=md-t1[j-(i>>1)];
     92     }
     93 }
     94 inline void p_de(int *f,int len)//derivative求导;f=f'
     95 {
     96     for(int i=0;i<len-1;++i)
     97         f[i]=ull(i+1)*f[i+1]%md;
     98     f[len-1]=0;
     99 }
    100 inline void p_in(int *f,int len)//integral积分;f=?f
    101 {
    102     for(int i=len-1;i>=1;--i)
    103         f[i]=ull(f[i-1])*inv[i]%md;
    104     f[0]=0;
    105 }
    106 void p_ln(int *f,int len)//要求len为2的幂,f[0]=1
    107 {
    108     static int t3[N];
    109     p_inv(f,t3,len);p_de(f,len);
    110     init(len<<1);
    111     dft(f,len<<1,1);dft(t3,len<<1,1);
    112     for(int i=0;i<(len<<1);++i)
    113         f[i]=ull(f[i])*t3[i]%md;
    114     dft(f,len<<1,-1);p_in(f,len);
    115 }
    116 void p_exp(int *f,int *g,int len)//要求len为2的幂,f[0]=0
    117 {
    118     static int t1[N],t2[N];
    119     g[0]=1;
    120     for(int i=2,j;i<=len;i<<=1)
    121     {
    122         memcpy(t1,g,sizeof(int)*(i>>1));
    123         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
    124         p_ln(t1,i);
    125         for(j=0;j<(i>>1);++j)
    126             t1[j]=del(f[j+(i>>1)],t1[j+(i>>1)]);
    127         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
    128         init(i);
    129         dft(t1,i,1);
    130         memcpy(t2,g,sizeof(int)*(i>>1));
    131         memset(t2+(i>>1),0,sizeof(int)*(i>>1));
    132         dft(t2,i,1);
    133         for(j=0;j<i;++j)
    134             t1[j]=ull(t1[j])*t2[j]%md;
    135         dft(t1,i,-1);
    136         for(j=i>>1;j<i;++j)
    137             g[j]=t1[j-(i>>1)];
    138     }
    139 }
    140 inline void p_pow_1(int *f,int *g,int len,int b)//要求len为2的幂,常数项为1
    141 {
    142     p_ln(f,len);
    143     for(int i=0;i<len;++i)
    144         f[i]=ull(f[i])*b%md;
    145     p_exp(f,g,len);
    146 }
    147 void p_pow(int *f,int *g,int len,int b)//g=f^b;要求len为2的幂
    148 {
    149     int i;ll p=-1;
    150     for(i=0;i<len;++i)
    151         if(f[i])
    152         {
    153             p=i;
    154             break;
    155         }
    156     if(p==-1)    return;
    157     for(i=0;i<len-p;++i)
    158         f[i]=f[i+p];
    159     memset(f+len-p,0,sizeof(int)*p);
    160     int t=f[0],t1=poww(t,md-2),t2=poww(t,b);
    161     for(i=0;i<len;++i)
    162         f[i]=ull(f[i])*t1%md;
    163     p_pow_1(f,g,len,b);
    164     for(i=0;i<len;++i)
    165         g[i]=ull(g[i])*t2%md;
    166     p*=b;
    167     for(i=len-1;i>=p;--i)
    168         g[i]=g[i-p];
    169     memset(g,0,sizeof(int)*min(ll(len),p));
    170 }
    171 int a[N],b[N];
    172 int n,n1,K;
    173 int main()
    174 {
    175     int i,t;
    176     inv[1]=1;
    177     for(i=2;i<=300000;++i)
    178         inv[i]=ull(md-md/i)*inv[md%i]%md;
    179     scanf("%d",&n);n1=n;
    180     char c;
    181     for(c=getchar();c<'0'||c>'9';c=getchar());
    182     for(;c>='0'&&c<='9';c=getchar())    K=(K*10LL+c-'0')%md;
    183     for(i=0;i<n;++i)
    184         scanf("%d",a+i);
    185     for(t=1;t<n;t<<=1);
    186     n=t;
    187     p_pow(a,b,n,K);
    188     for(i=0;i<n1;++i)
    189         printf("%d ",b[i]);
    190     return 0;
    191 }
    View Code

    版本1.1:基于此题版本1,输入三个b分别表示对mod和mod-1取模的结果以及min(原始b,长度)

    这里可以交orzzzy

      1 #prag
      2 ma GCC optimize(2)
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<vector>
      7 #include<cmath>
      8 using namespace std;
      9 #define fi first
     10 #define se second
     11 #define mp make_pair
     12 #define pb push_back
     13 typedef long long ll;
     14 typedef unsigned long long ull;
     15 const int md=998244353;
     16 const int N=2097152;
     17 #define delto(a,b) ((a)-=(b),((a)<0)&&((a)+=md))
     18 inline int del(int a,int b)
     19 {
     20     a-=b;
     21     return a<0?a+md:a;
     22 }
     23 int rev[N];
     24 void init(int len)
     25 {
     26     int bit=0,i;
     27     while((1<<(bit+1))<=len)    ++bit;
     28     for(i=1;i<len;++i)
     29         rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
     30 }
     31 ull poww(ull a,ull b)
     32 {
     33     ull ans=1;
     34     for(;b;b>>=1,a=a*a%md)
     35         if(b&1)
     36             ans=ans*a%md;
     37     return ans;
     38 }
     39 int inv[3000011];
     40 void dft(int *a,int len,int idx)//要求len为2的幂
     41 {
     42     int i,j,k,t1,t2;ull wn,wnk;
     43     for(i=0;i<len;++i)
     44         if(i<rev[i])
     45             swap(a[i],a[rev[i]]);
     46     for(i=1;i<len;i<<=1)
     47     {
     48         wn=poww(idx==1?3:332748118,(md-1)/(i<<1));
     49         for(j=0;j<len;j+=(i<<1))
     50         {
     51             wnk=1;
     52             for(k=j;k<j+i;++k,wnk=wnk*wn%md)
     53             {
     54                 t1=a[k];t2=a[k+i]*wnk%md;
     55                 a[k]+=t2;
     56                 (a[k]>=md)&&(a[k]-=md);
     57                 a[k+i]=t1-t2;
     58                 (a[k+i]<0)&&(a[k+i]+=md);
     59             }
     60         }
     61     }
     62     if(idx==-1)
     63     {
     64         ull ilen=inv[len];
     65         for(i=0;i<len;++i)
     66             a[i]=a[i]*ilen%md;
     67     }
     68 }
     69 void p_inv(int *f,int *g,int len)//g=f^(-1);f,g数组的长度不小于2len(需要足够长用于临时存放元素);要求len是2的幂
     70 {
     71     static int t1[N],t2[N];
     72     g[0]=poww(f[0],md-2);
     73     for(int i=2,j;i<=len;i<<=1)
     74     {
     75         memcpy(t1,f,sizeof(int)*i);
     76         memcpy(t2,g,sizeof(int)*(i>>1));
     77         memset(t2+(i>>1),0,sizeof(int)*(i>>1));
     78         init(i);
     79         dft(t1,i,1);dft(t2,i,1);
     80         for(j=0;j<i;++j)
     81             t1[j]=ull(t1[j])*t2[j]%md;
     82         dft(t1,i,-1);
     83         for(j=0;j<(i>>1);++j)
     84             t1[j]=t1[j+(i>>1)];
     85         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
     86         dft(t1,i,1);
     87         for(j=0;j<i;++j)
     88             t1[j]=ull(t1[j])*t2[j]%md;
     89         dft(t1,i,-1);
     90         for(j=i>>1;j<i;++j)
     91             g[j]=md-t1[j-(i>>1)];
     92     }
     93 }
     94 inline void p_de(int *f,int len)//derivative求导;f=f'
     95 {
     96     for(int i=0;i<len-1;++i)
     97         f[i]=ull(i+1)*f[i+1]%md;
     98     f[len-1]=0;
     99 }
    100 inline void p_in(int *f,int len)//integral积分;f=?f
    101 {
    102     for(int i=len-1;i>=1;--i)
    103         f[i]=ull(f[i-1])*inv[i]%md;
    104     f[0]=0;
    105 }
    106 void p_ln(int *f,int len)//要求len为2的幂,f[0]=1
    107 {
    108     static int t3[N];
    109     p_inv(f,t3,len);p_de(f,len);
    110     init(len<<1);
    111     dft(f,len<<1,1);dft(t3,len<<1,1);
    112     for(int i=0;i<(len<<1);++i)
    113         f[i]=ull(f[i])*t3[i]%md;
    114     dft(f,len<<1,-1);p_in(f,len);
    115 }
    116 void p_exp(int *f,int *g,int len)//要求len为2的幂,f[0]=0
    117 {
    118     static int t1[N],t2[N];
    119     g[0]=1;
    120     for(int i=2,j;i<=len;i<<=1)
    121     {
    122         memcpy(t1,g,sizeof(int)*(i>>1));
    123         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
    124         p_ln(t1,i);
    125         for(j=0;j<(i>>1);++j)
    126             t1[j]=del(f[j+(i>>1)],t1[j+(i>>1)]);
    127         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
    128         init(i);
    129         dft(t1,i,1);
    130         memcpy(t2,g,sizeof(int)*(i>>1));
    131         memset(t2+(i>>1),0,sizeof(int)*(i>>1));
    132         dft(t2,i,1);
    133         for(j=0;j<i;++j)
    134             t1[j]=ull(t1[j])*t2[j]%md;
    135         dft(t1,i,-1);
    136         for(j=i>>1;j<i;++j)
    137             g[j]=t1[j-(i>>1)];
    138     }
    139 }
    140 inline void p_pow_1(int *f,int *g,int len,int b)//要求len为2的幂,常数项为1
    141 {
    142     p_ln(f,len);
    143     for(int i=0;i<len;++i)
    144         f[i]=ull(f[i])*b%md;
    145     p_exp(f,g,len);
    146 }
    147 void p_pow(int *f,int *g,int len,int b1,int b2,int b3)//g=f^b;要求len为2的幂
    148 {
    149     int i;ll p=-1;
    150     for(i=0;i<len;++i)
    151         if(f[i])
    152         {
    153             p=i;
    154             break;
    155         }
    156     if(p==-1)    return;
    157     for(i=0;i<len-p;++i)
    158         f[i]=f[i+p];
    159     memset(f+len-p,0,sizeof(int)*p);
    160     int t=f[0],t1=poww(t,md-2),t2=poww(t,b2);
    161     for(i=0;i<len;++i)
    162         f[i]=ull(f[i])*t1%md;
    163     p_pow_1(f,g,len,b1);
    164     for(i=0;i<len;++i)
    165         g[i]=ull(g[i])*t2%md;
    166     p*=b3;
    167     for(i=len-1;i>=p;--i)
    168         g[i]=g[i-p];
    169     memset(g,0,sizeof(int)*min(ll(len),p));
    170 }
    171 int a[N],b[N];
    172 int n,n1,K1,K2;ll K3;
    173 int main()
    174 {
    175     int i,t;
    176     inv[1]=1;
    177     for(i=2;i<=3000000;++i)
    178         inv[i]=ull(md-md/i)*inv[md%i]%md;
    179     scanf("%d",&n);n1=n;
    180     char c;
    181     for(c=getchar();c<'0'||c>'9';c=getchar());
    182     for(;c>='0'&&c<='9';c=getchar())
    183     {
    184         K1=(K1*10LL+c-'0')%md;
    185         K2=(K2*10LL+c-'0')%(md-1);
    186         if(K3<=n)    K3=K3*10LL+c-'0';
    187     }
    188     K3=min(K3,ll(n));
    189     for(i=0;i<n;++i)
    190         scanf("%d",a+i);
    191     for(t=1;t<n;t<<=1);
    192     n=t;
    193     p_pow(a,b,n,K1,K2,K3);
    194     for(i=0;i<n1;++i)
    195         printf("%d ",b[i]);
    196     return 0;
    197 }
    View Code
  • 相关阅读:
    pycharm设置linux中的python解析器进行本地开发
    linux安装python
    Jenkins自动构建的几种方式
    接口加密
    python接口自动化—unittest 常用的断言方法
    cookie 组成结构
    post请求的四种数据格式
    jmeter之数据库相关
    jmeter函数简介
    java_第一年_JDBC(6)
  • 原文地址:https://www.cnblogs.com/hehe54321/p/10577535.html
Copyright © 2011-2022 走看看