洛谷P4725 【模板】多项式对数函数

时间:2019-03-19
本文章向大家介绍洛谷P4725 【模板】多项式对数函数,主要包括洛谷P4725 【模板】多项式对数函数使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

注释:

$e^x$与$ln(1-x)$的麦克劳林级数:

$e^x=\sum_{i=0}\frac{x^i}{i!}$

$ln(1-x)=-\sum_{i=1}\frac{x^i}{i}$

多项式ln,exp就是用这个定义的

以及,在求ln(y)时的注意点:

令1-x=y,x=1-y,如果y的常数项不为1,那么x的常数项一定不为0。ln(y)=ln(1-x)=$-\sum_{i=1}\frac{x^i}{i}$

x的常数项a对于式子的右侧产生的贡献是$-\sum_{i=1}\frac{a^i}{i}=ln(1-a)$(或者说ln(y)的常数项是这个),当a不为0时这个东西模意义下一般都没办法算

做法:看题解 https://www.luogu.org/problemnew/solution/P4725

设G(x)=ln(F(x))

两边同时求导,得$G'(x)=ln'(F(x))F'(x)=\frac{F'(x)}{F(x)}$

这样可以求出G'(x),积分后得到G(x)除常数项之外的项

常数项怎么办?

根据”注释“的最后一句,G(x)常数项等于模意义下ln(F(x)的常数项),反正F的常数项不为1时,我不会算;刚好题目保证F的常数项为1,那么G(x)常数项就是0

  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=131072;
 17 int rev[N<<1];
 18 void init(int len)
 19 {
 20     int bit=0,i;
 21     while((1<<(bit+1))<=len)    ++bit;
 22     for(i=0;i<len;++i)
 23         rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
 24 }
 25 ll poww(ll a,ll b)
 26 {
 27     ll base=a,ans=1;
 28     for(;b;b>>=1,base=base*base%md)
 29         if(b&1)
 30             ans=ans*base%md;
 31     return ans;
 32 }
 33 void dft(int *a,int len,int idx)//要求len为2的幂
 34 {
 35     int i,j,k,t1,t2;ll wn,wnk;
 36     for(i=0;i<len;++i)
 37         if(i<rev[i])
 38             swap(a[i],a[rev[i]]);
 39     for(i=1;i<len;i<<=1)
 40     {
 41         wn=poww(idx==1?3:332748118,(md-1)/(i<<1));
 42         for(j=0;j<len;j+=(i<<1))
 43         {
 44             wnk=1;
 45             for(k=j;k<j+i;++k,wnk=wnk*wn%md)
 46             {
 47                 t1=a[k];t2=a[k+i]*wnk%md;
 48                 a[k]+=t2;
 49                 (a[k]>=md) && (a[k]-=md);
 50                 a[k+i]=t1-t2;
 51                 (a[k+i]<0) && (a[k+i]+=md);
 52             }
 53         }
 54     }
 55     if(idx==-1)
 56     {
 57         ll ilen=poww(len,md-2);
 58         for(i=0;i<len;++i)
 59             a[i]=a[i]*ilen%md;
 60     }
 61 }
 62 void p_inv(int *f,int *g,int len)//g=f^(-1);f,g数组的长度不小于2^(ceil(log2(len))+1)(需要足够长用于临时存放元素) 
 63 {
 64     static int t1[N<<1];
 65     int n1=2;
 66     for(;n1<(len<<1);n1<<=1);
 67     memset(f+len,0,sizeof(int)*(n1-len));
 68     g[0]=poww(f[0],md-2);
 69     for(int i=2,j;i<(len<<1);i<<=1)
 70     {
 71         init(i<<1);
 72         memcpy(t1,f,sizeof(int)*i);
 73         memset(t1+i,0,sizeof(int)*i);
 74         memset(g+(i>>1),0,sizeof(int)*(i+(i>>1)));
 75         dft(t1,i<<1,1);dft(g,i<<1,1);
 76         for(j=0;j<(i<<1);++j)
 77             g[j]=ll(g[j])*(2+ll(md-g[j])*t1[j]%md)%md;
 78         dft(g,i<<1,-1);
 79     }
 80     memset(g+len,0,sizeof(int)*(n1-len));
 81 }
 82 int inv[300011];
 83 inline void p_de(int *f,int len)//derivative求导;f=f'
 84 {
 85     for(int i=0;i<len-1;++i)
 86         f[i]=ll(i+1)*f[i+1]%md;
 87     f[len-1]=0;
 88 }
 89 inline void p_in(int *f,int len)//integral积分;f=?f
 90 {
 91     for(int i=len-1;i>=1;--i)
 92         f[i]=ll(f[i-1])*inv[i]%md;
 93     f[0]=0;
 94 }
 95 void p_ln(int *f,int len)//f=ln(f);f长度满足inv的限制
 96 {
 97     static int t1[N<<1];
 98     int n1=1,i;
 99     while(n1<len)    n1<<=1;
100     memset(f+len,0,sizeof(int)*(n1-len));
101     p_inv(f,t1,n1);p_de(f,n1);
102     init(n1<<1);
103     dft(f,n1<<1,1);dft(t1,n1<<1,1);
104     for(i=0;i<(n1<<1);++i)
105         f[i]=ll(f[i])*t1[i]%md;
106     dft(f,n1<<1,-1);
107     p_in(f,n1);
108 }
109 int a[N<<1];
110 int n;
111 int main()
112 {
113     int i;
114     inv[1]=1;
115     for(i=2;i<=300000;++i)
116         inv[i]=ll(md-md/i)*inv[md%i]%md;
117     scanf("%d",&n);
118     for(i=0;i<n;++i)
119         scanf("%d",a+i);
120     //for(int iii=1,p=n;iii<=50;++iii)
121     //    a[p++]=rand()%md;
122     p_ln(a,n);
123     for(i=0;i<n;++i)
124         printf("%d ",a[i]);
125     return 0;
126 }
View Code