题目:https://www.luogu.org/problemnew/show/P3784

   https://www.lydsy.com/JudgeOnline/problem.php?id=4913

和洛谷3489“付公主的背包”一样的套路。

要设 a[ i ] 表示第 i 个值有没有出现。

然后就有 \( \prod\limits_i(\frac{1}{1-x^i})^{a_i} = f(x) \)

因为有 \( \prod \) ,所以两边取 ln 。

\( \sum\limits_{i}a_{i}ln(\frac{1}{1-x^i}) = ln(f(x)) \)

现在想求一个 \( ln(\frac{1}{1-x^i}) \) 的更优美的形式(一般是形如 \( \sum \) 的),来更简单地刻画 a[ i ] 和 f[ i ] 的关系。(f[ i ] 是 ln( f(x) ) 的第 i 项系数)

因为有 \( ln \) ,所以先求导再积分来化式子。

并且 \( \frac{f'(x)}{f(x)} \) 了之后,把 \( f'(x) \) 写成 \( \sum \) 的形式,用 \( f(x) \) 和 \( \int \) 化出一个更好看的 \( \sum \) 的式子。

\( \int (1-x^i)\sum\limits_{j=1}i*j*x^{i*j-1} \) // j 从 1 开始

\( = \int \sum\limits_{j=1}i*j*x^{i*j-1} - \sum\limits_{j=1}i*j*x^{i*(j+1)-1} \)

\( = \int \sum\limits_{j=1}i*x^{i*j-1} \)

\( = \sum\limits_{j=0}\frac{1}{j}*x^{i*j} \)

所以 \( \sum\limits_{i=1}a_i\sum\limits_{j=0}\frac{1}{j}x^{i*j} = ln(f(x)) \)

  \( \sum\limits_{i=1}\sum\limits_{j=0}a_i*\frac{1}{j} = f[i*j] \)

\( f[i]=\sum\limits_{j\|i}a_j*\frac{j}{i} \)

把分母的 i 乘到左边,然后莫比乌斯反演一下就知道 \( a_i *i= \sum\limits_{j\|i}f[j]*j*u(i/j) \)

实现的时候要写 MTT 。写拆系数 FFT 的话需要 long double 。自己写的三模数 NTT 还没调出来,不知是哪里出错。

有许许多多的细节需要注意。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cmath>
  5. #define db long double
  6. #define ll long long
  7. using namespace std;
  8. int rdn()
  9. {
  10. int ret=;bool fx=;char ch=getchar();
  11. while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
  12. while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
  13. return fx?ret:-ret;
  14. }
  15. const int N=(<<)+;
  16. int n,p,f[N],g[N],u[N],pri[N]; bool vis[N];
  17.  
  18. int upt(int x){if(x>=p)x-=p;if(x<)x+=p;return x;}
  19. int pw(int x,int k)
  20. {int ret=;while(k){if(k&)ret=(ll)ret*x%p;x=(ll)x*x%p;k>>=;}return ret;}
  21.  
  22. namespace poly{
  23. const db pi=acos(-);
  24. struct cpl{
  25. db x,y;
  26. cpl(db x=,db y=):x(x),y(y) {}
  27. cpl operator+ (const cpl &b)const
  28. {return cpl(x+b.x,y+b.y);}
  29. cpl operator- (const cpl &b)const
  30. {return cpl(x-b.x,y-b.y);}
  31. cpl operator* (const cpl &b)const
  32. {return cpl(x*b.x-y*b.y,x*b.y+y*b.x);}
  33. cpl operator/ (const int &b)const
  34. {return cpl(x/b,y/b);}
  35. };
  36. cpl conj(cpl a){return cpl(a.x,-a.y);}
  37. int len,r[N],inv[N]; cpl Wn[N];
  38. int bs,pbs,bs2; cpl pa[N],pb[N],pc[N],pd[N];
  39. int A[N],B[N],tp[N];
  40.  
  41. void init()
  42. {
  43. int tmp=sqrt(p);
  44. for(bs=,pbs=;pbs<=tmp;bs++,pbs<<=);
  45. bs2=bs<<; pbs--;
  46. }
  47. void fft_pre()
  48. {
  49. for(int i=,j=len>>;i<len;i++)
  50. r[i]=(r[i>>]>>)+((i&)?j:);
  51. for(int R=,m=;R<=len;m=R,R<<=)
  52. Wn[R]=cpl( cos(pi/m),sin(pi/m) );
  53. }
  54. void fft(cpl *a,bool fx)
  55. {
  56. for(int i=;i<len;i++)
  57. if(i<r[i])swap(a[i],a[r[i]]);
  58. for(int R=;R<=len;R<<=)
  59. {
  60. cpl wn=fx?conj(Wn[R]):Wn[R];
  61. for(int i=,m=R>>;i<len;i+=R)
  62. {
  63. cpl w=cpl(,);
  64. for(int j=;j<m;j++,w=w*wn)
  65. {
  66. cpl x=a[i+j], y=w*a[i+m+j];
  67. a[i+j]=x+y; a[i+m+j]=x-y;
  68. }
  69. }
  70. }
  71. if(!fx)return;
  72. for(int i=;i<len;i++)a[i]=a[i]/len;
  73. }
  74. void mtt(int n1,int *a,int n2,int *b,int *c)
  75. {
  76. int n3=n1+n2-;
  77. for(len=;len<n3;len<<=); fft_pre();
  78. //for(int i=0;i<n1;i++) pa[i]=cpl(a[i]>>15,a[i]&32767);
  79. //for(int i=0;i<n2;i++) pb[i]=cpl(b[i]>>15,b[i]&32767);
  80. for(int i=;i<n1;i++) pa[i]=cpl(a[i]>>bs,a[i]&pbs);
  81. for(int i=;i<n2;i++) pb[i]=cpl(b[i]>>bs,b[i]&pbs);
  82. for(int i=n1;i<len;i++) pa[i]=cpl(,);
  83. for(int i=n2;i<len;i++) pb[i]=cpl(,);
  84. fft(pa,); fft(pb,);
  85. pa[len]=pa[]; pb[len]=pb[];
  86. for(int i=,j=len;i<len;i++,j--)//q[i]=conj(p[j])
  87. {
  88. cpl ta=(pa[i]+conj(pa[j]))*cpl(0.5,);//conj(*[j])!!
  89. cpl tb=(pa[i]-conj(pa[j]))*cpl(,-0.5);
  90. cpl tc=(pb[i]+conj(pb[j]))*cpl(0.5,);
  91. cpl td=(pb[i]-conj(pb[j]))*cpl(,-0.5);
  92. pc[i]=ta*tc+ta*td*cpl(,);
  93. pd[i]=tb*tc+tb*td*cpl(,);
  94. }
  95. pa[]=pb[]=cpl(,);
  96. fft(pc,); fft(pd,);
  97. for(int i=;i<n3;i++)
  98. {
  99. ll ta=(ll)(pc[i].x+0.5)%p;
  100. ll tb=(ll)(pc[i].y+0.5)%p;
  101. ll tc=(ll)(pd[i].x+0.5)%p;
  102. ll td=(ll)(pd[i].y+0.5)%p;
  103. c[i]=((ta<<bs2)+((tb+tc)<<bs)+td)%p;
  104. //c[i]=((ta<<30)+((tb+tc)<<15)+td)%p;
  105. }
  106. }
  107. void get_dao(int n,int *a,int *b)
  108. {
  109. for(int i=;i<n;i++)b[i-]=(ll)a[i]*i%p;
  110. b[n-]=;
  111. }
  112. void get_jf(int n,int *a,int *b)
  113. {
  114. inv[]=;
  115. for(int i=;i<n;i++)inv[i]=(ll)(p-p/i)*inv[p%i]%p;//(p-..)!
  116. for(int i=n-;i;i--)b[i]=(ll)a[i-]*inv[i]%p;//i-- for a==b
  117. b[]=;
  118. }
  119. void get_inv(int n,int *a,int *b)
  120. {
  121. b[]=pw(a[],p-);
  122. for(int l=;l<=n;l<<=)
  123. {
  124. for(int i=l>>;i<l;i++)b[i]=;/////
  125. mtt(l,a,l,b,tp);
  126. mtt(l,b,l,tp,tp);/////b*tp not a*tp
  127. for(int i=;i<l;i++)
  128. b[i]=((ll)b[i]*-tp[i]+p)%p;
  129. }
  130. }
  131. void get_ln(int n,int *a,int *b)
  132. {
  133. get_dao(n,a,A); get_inv(n,a,B);
  134. mtt(n,A,n,B,A);
  135. get_jf(n,A,b);
  136. }
  137. }
  138. void get_mu(int n)
  139. {
  140. int cnt=; u[]=;
  141. for(int i=,d;i<=n;i++)
  142. {
  143. if(!vis[i])pri[++cnt]=i,u[i]=-;
  144. for(int j=;j<=cnt&&(d=i*pri[j])<=n;j++)
  145. {
  146. vis[d]=; u[d]=-u[i];
  147. if(i%pri[j]==){u[d]=; break;}
  148. }
  149. }
  150. }
  151. int main()
  152. {
  153. n=rdn();p=rdn(); poly::init();//
  154. for(int i=;i<=n;i++)f[i]=rdn(); f[]=;//f[0]=1
  155. int l=;for(;l<=n;l<<=);//<=n
  156. poly::get_ln(l,f,f); get_mu(n);
  157. for(int i=;i<=n;i++)f[i]=(ll)f[i]*i%p;
  158. for(int i=;i<=n;i++)
  159. for(int j=,k=i;k<=n;j++,k+=i)
  160. g[k]=upt(g[k]+f[i]*u[j]);
  161. int cnt=;
  162. for(int i=;i<=n;i++)if(g[i])cnt++;
  163. printf("%d\n",cnt);
  164. for(int i=;i<=n;i++)if(g[i])printf("%d ",g[i]);
  165. puts(""); return ;
  166. }

拆系数FFT

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define ll long long
  5. using namespace std;
  6. int rdn()
  7. {
  8. int ret=;bool fx=;char ch=getchar();
  9. while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
  10. while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
  11. return fx?ret:-ret;
  12. }
  13. int upt(int x,int mod)
  14. {while(x>=mod)x-=mod;while(x<)x+=mod;return x;}
  15. int pw(int x,int k,int mod)
  16. {int ret=;while(k){if(k&)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=;}return ret;}
  17.  
  18. const int N=(<<)+; int p;
  19. namespace poly{
  20. const double eps=1e-;
  21. int m[]={,,};
  22. ll M=(ll)m[]*m[], A[N],B[N],C[][N];
  23. int len,r[N],Wn[N][],inv[N];
  24. int tp[N],ta[N],tb[N];
  25. ll mul(ll a,ll b,ll mod)
  26. {
  27. a=(a%mod+mod)%mod; b=(b%mod+mod)%mod;/////
  28. ll ret=(a*b- (ll)((long double)a/mod*b+eps) *mod)%mod;
  29. if(ret<)ret+=mod; return ret;
  30. }
  31. void ntt_pre(int len,int mod)
  32. {
  33. for(int R=;R<=len;R<<=)
  34. Wn[R][]=pw( ,(mod-)/R,mod ),
  35. Wn[R][]=pw( ,(mod-)-(mod-)/R,mod );
  36. }
  37. void ntt(ll *a,bool fx,int mod)
  38. {
  39. for(int i=;i<len;i++)
  40. if(i<r[i])swap(a[i],a[r[i]]);
  41. for(int R=;R<=len;R<<=)
  42. {
  43. int wn=Wn[R][fx];
  44. for(int i=,m=R>>;i<len;i+=R)
  45. for(int j=,w=;j<m;j++,w=(ll)w*wn%mod)
  46. {
  47. int x=a[i+j], y=(ll)w*a[i+m+j]%mod;
  48. a[i+j]=upt(x+y,mod); a[i+m+j]=upt(x-y,mod);
  49. }
  50. }
  51. if(!fx)return; int inv=pw(len,mod-,mod);
  52. for(int i=;i<len;i++)a[i]=(ll)a[i]*inv%mod;
  53. }
  54. void mtt(int n,int *a,int n2,int *b,int *c)//ok if c==a||c==b
  55. {
  56. for(len=;len<n+n2;len<<=); int mod;
  57. for(int i=,j=len>>;i<len;i++)
  58. r[i]=(r[i>>]>>)+((i&)?j:);
  59. for(int i=;i<;i++)
  60. {
  61. mod=m[i];
  62. for(int j=;j<n;j++)A[j]=a[j];
  63. for(int j=n;j<len;j++)A[j]=;
  64. for(int j=;j<n2;j++)B[j]=b[j];
  65. for(int j=n2;j<len;j++)B[j]=;
  66. ntt_pre(len,mod);
  67. ntt(A,,mod); ntt(B,,mod);
  68. for(int j=;j<len;j++)C[i][j]=(ll)A[j]*B[j]%mod;
  69. ntt(C[i],,mod);
  70. }
  71. len=n+n2-;//n-1 + m-1 = n+m-2
  72. mod=m[]; int tm=m[],inv=pw(tm,mod-,mod);
  73. for(int i=;i<len;i++)
  74. {
  75. int tmp=(ll)upt(C[][i]-C[][i],mod)*inv%mod;
  76. c[i]=((ll)tmp*tm+C[][i])%M;
  77. }
  78. mod=p; tm=m[]; inv=pw(M%tm,tm-,tm);
  79. for(int i=;i<len;i++)
  80. {
  81. int tmp=mul((C[][i]-c[i])%tm+tm,inv,tm);
  82. c[i]=(mul(tmp,M,mod)+c[i])%mod;
  83. }
  84. }
  85. void get_dao(int n,int *a,int *b)
  86. {
  87. for(int i=;i<n;i++)b[i-]=(ll)a[i]*i%p;
  88. b[n-]=;
  89. }
  90. void get_jf(int n,int *a,int *b)
  91. {
  92. inv[]=;
  93. for(int i=;i<n;i++)inv[i]=(ll)(p-p/i)*inv[p%i]%p;//p/i
  94. for(int i=n-;i;i--)b[i]=(ll)a[i-]*inv[i]%p;//i--:a==b
  95. b[]=;
  96. }
  97. void get_inv(int n,int *a,int *b)//tb[]
  98. {
  99. b[]=pw(a[],p-,p);
  100. for(int l=,tn=;tn<n;tn=l,l<<=)
  101. {
  102. for(int i=tn;i<l;i++)b[i]=;
  103. mtt(l,a,l,b,tb);
  104. mtt(l,b,l,tb,tb);
  105. for(int i=;i<l;i++)
  106. b[i]=((ll)b[i]*-tb[i]+p)%p;
  107. }
  108. }
  109. void get_ln(int n,int *a,int *b)//ta[],tp[]//ok if b==a
  110. {//%x^n
  111. get_dao(n,a,ta); get_inv(n,a,tp);
  112. mtt(n,ta,n,tp,ta);
  113. get_jf(n,ta,b);
  114. }
  115. }
  116.  
  117. int n,f[N],ans[N],mu[N],pri[N]; bool vis[N];
  118. void get_mu(int n)
  119. {
  120. mu[]=; int cnt=;
  121. for(int i=;i<=n;i++)
  122. {
  123. if(!vis[i])pri[++cnt]=i,mu[i]=-;
  124. for(int j=,d;j<=cnt&&(d=i*pri[j])<=n;j++)
  125. {
  126. vis[d]=;
  127. if(i%pri[j]==){mu[d]=;break;}
  128. mu[d]=-mu[i];
  129. }
  130. }
  131. }
  132. int main()
  133. {
  134. n=rdn();p=rdn();
  135. for(int i=;i<=n;i++)f[i]=rdn(); f[]=;//f[0]=1
  136. poly::get_ln(n+,f,f);//n+1
  137. for(int i=;i<=n;i++)f[i]=(ll)f[i]*i%p;
  138. get_mu(n);
  139. for(int i=;i<=n;i++)
  140. for(int j=,k=i;k<=n;j++,k+=i)
  141. ans[k]=upt(ans[k]+mu[j]*f[i],p);
  142. int cnt=;
  143. for(int i=;i<=n;i++)if(ans[i])cnt++;
  144. printf("%d\n",cnt);
  145. for(int i=;i<=n;i++)if(ans[i])printf("%d ",ans[i]);
  146. puts(""); return ;
  147. }

三模数NTT(TLE+WA)

洛谷 3784(bzoj 4913) [SDOI2017]遗忘的集合——多项式求ln+MTT的更多相关文章

  1. BZOJ 4913 [Sdoi2017] 遗忘的集合

    骂了隔壁的 BZOJ垃圾评测机 我他妈卡了两页的常数了 我们机房的电脑跑的都比BZOJ快

  2. 洛谷 P2155 BZOJ 2186 codevs 2301 [SDOI2008]沙拉公主的困惑

    题目描述 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票.房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的 ...

  3. [SDOI2017]遗忘的集合

    [SDOI2017]遗忘的集合 综合了很多套路的题 一看就是完全背包 生成函数! 转化为连乘积形式 Pi....=F 求Ln! 降次才可以解方程 发现方程是: f[i]=∑t|i : bool(t)* ...

  4. 洛谷5月月赛T30212 玩游戏 【分治NTT + 多项式求ln】

    题目链接 洛谷T30212 题解 式子很容易推出来,二项式定理展开后对于\(k\)的答案即可化简为如下: \[k!(\sum\limits_{i = 0}^{k} \frac{\sum\limits_ ...

  5. 洛谷 P3307: bzoj 3202: [SDOI2013] 项链

    题目传送门:洛谷P3307.这题在bzoj上是权限题. 题意简述: 这题分为两个部分: ① 有一些珠子,每个珠子可以看成一个无序三元组.三元组要满足三个数都在$1$到$m$之间,并且三个数互质,两个珠 ...

  6. 洛谷 4106 / bzoj 3614 [HEOI2014]逻辑翻译——思路+类似FWT

    题目:https://www.luogu.org/problemnew/show/P4106 https://www.lydsy.com/JudgeOnline/problem.php?id=3614 ...

  7. 洛谷 P3332 BZOJ 3110 [ZJOI2013]K大数查询

    题目链接 洛谷 bzoj 题解 整体二分 Code #include<bits/stdc++.h> #define LL long long #define RG register usi ...

  8. 洛谷 P2486 BZOJ 2243 [SDOI2011]染色

    题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221” ...

  9. 洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓

    题目描述 本题中,我们将用符号表示对c向下取整,例如:. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只 ...

随机推荐

  1. 全源最短路径 - floyd算法 - O(N ^ 3)

    Floyd-Warshall算法的原理是动态规划. 设Di,j,k为从i到j的只以(1..k)集合中的节点为中间节点的最短路径的长度. 若最短路径经过点k,则Di,j,k = Di,k,k − 1 + ...

  2. OC 属性关键字

    // 属性关键字 /* 1.ARC下(自动管理内存,自动引用计数)(IOS) strong,weak ----------------------------------------- 2.MRC下( ...

  3. echatrs可视化图在隐藏后显示不出来或是宽度出现问题

    最近在做一个可视化的项目,用了百度的ECharts.js作为可视化的视图框架,echarts的实例很多,基本能满足项目的需求,而且文档也相对完整.清晰,是个很不错的前端可视化框架. 我们的项目是使用b ...

  4. 模拟QQ分组(具有伸缩功能) (添加开源框架的光闪烁效果)SimpleExpandableListAdapter 适配器的用法,并且可添加组及其组内数据。

    package com.lixu.qqfenzu; import java.util.ArrayList; import java.util.HashMap; import java.util.Lis ...

  5. RM报表 实际打印的判断

    procedure TFormDZMD.RMReport1PrintReportEvent(Sender: TObject); begin // Log('RMReport1PrintReportEv ...

  6. 4K电视与4K显示器的选择

    目前主流的电脑显示器分辨率是1920x1080,也就是常说的FHD标准,不过在智能手机都开始朝2560x1440前进了,PC显示器显然还需要更进一步的强化,下一代的标准就是4K分辨率,也就是Utlra ...

  7. ASI 实现注册方法的小例子(get和post方式)

    服务端文档: 注册 /my/register.php 输入参数: 参数说明: username 用户名 password 密码 email 邮箱 成功返回值:{"code": &q ...

  8. Android Mms之:深入MMS支持

    Composing and editing MMS在Android Mms应用里面的具体实现形式,或数据结构是SlideshowModel,它是一个每个节点为SlideModel的ArrayList, ...

  9. TreeMap源码学习

    这是看过的第一个jdk源码(从立下目标以来):TreeMap.说实话断断续续的看了有好几天了,我觉得我犯了一个错误,就像一开始说的那样,我打算完完全全看懂TreeMap关于红黑树的实现方式,后来我想了 ...

  10. Binary file to C array(bin2c)

    /******************************************************************************** * Binary file to C ...