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