[关闭]
@y20070316 2017-04-27T01:28:14.000000Z 字数 2106 阅读 920

XSY 2263 - Grasshoppers

题目精选 FFT 生成函数


分析

  每次变换的意义相当于: 生成函数在循环卷积的意义下, 乘上 . 所以求出 即可.

实现

FFT注意事项:
1. 变换过去就变换不回来了.
2. 如果精度要求不高, 那么就是用 round, 否则使用 (int)(x+0.5) , 但是这样只能用于 正数 .

代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <algorithm>
  6. using namespace std;
  7. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  8. #define LL long long
  9. #define LD long double
  10. const int N=300000;
  11. const LD PI=acos(-1);
  12. int n,m,t;
  13. int a[N];
  14. struct Comp {
  15. LD x,y;
  16. Comp(LD _x=0,LD _y=0):x(_x),y(_y) {}
  17. friend Comp operator + (Comp a,Comp b) { return Comp(a.x+b.x,a.y+b.y); }
  18. friend Comp operator - (Comp a,Comp b) { return Comp(a.x-b.x,a.y-b.y); }
  19. friend Comp operator * (Comp a,Comp b) { return Comp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x); }
  20. }B[N],C[N],A[N];
  21. int bit,len;
  22. int rev[N];
  23. Comp wi[N],wv[N];
  24. int rd(void) {
  25. int f=1; char c=getchar(); for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  26. int x=0; for (;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
  27. }
  28. void Init(int siz) {
  29. for (bit=0,len=1;len<siz;bit++,len<<=1);
  30. for (int i=0;i<len;i++) rev[i]=rev[i>>1]>>1|(i&1)<<(bit-1);
  31. for (int i=1,k=(1<<i);i<=bit;k=(1<<++i)) {
  32. wi[k]=Comp(cos(2*PI/+k),sin(2*PI/+k));
  33. wv[k]=Comp(cos(2*PI/-k),sin(2*PI/-k));
  34. }
  35. }
  36. void FFT(Comp *A,int sign) {
  37. for (int i=0;i<len;i++) if (i<rev[i]) swap(A[i],A[rev[i]]);
  38. for (int i=2;i<=len;i<<=1) {
  39. Comp wn=( sign==+1?wi[i]:wv[i] );
  40. for (int j=0;j<len;j+=i) {
  41. Comp w(1,0);
  42. for (int k=0;k<i/2;k++) {
  43. Comp x=A[j+k], y=w*A[j+k+i/2];
  44. A[j+k]=x+y, A[j+k+i/2]=x-y;
  45. w=w*wn;
  46. }
  47. }
  48. }
  49. if (sign==-1)
  50. for (int i=0;i<len;i++)
  51. A[i]=Comp(A[i].x/len,0);
  52. }
  53. void Transfer(Comp *A) {
  54. static int tmp[N];
  55. for (int i=0;i<n;i++)
  56. tmp[i]=( (LL)round(A[i].x)+(LL)round(A[i+n].x) )%m;
  57. for (int i=0;i<len;i++)
  58. A[i]=(i<n?tmp[i]:0);
  59. }
  60. int T(double x) { return (((int)round(x)-1)%m+m)%m+1; }
  61. int main(void) {
  62. #ifndef ONLINE_JUDGE
  63. freopen("A.in","r",stdin);
  64. #endif
  65. n=rd(),m=rd(),t=rd(); F(i,1,n) a[i]=rd();
  66. Init((n-1)+(n-1)+1);
  67. B[0]=C[0]=-1, B[n-1]=C[n-1]=2; t--;
  68. for (;t>0;t>>=1) {
  69. static Comp tmp[N]; memcpy(tmp,B,sizeof B);
  70. FFT(tmp,+1);
  71. if (t%2==1) {
  72. FFT(C,+1);
  73. for (int i=0;i<len;i++) C[i]=C[i]*tmp[i];
  74. FFT(C,-1);
  75. Transfer(C);
  76. }
  77. FFT(B,+1);
  78. for (int i=0;i<len;i++) B[i]=B[i]*tmp[i];
  79. FFT(B,-1);
  80. Transfer(B);
  81. }
  82. F(i,1,n) A[i%n]=a[i];
  83. FFT(A,+1);
  84. FFT(C,+1);
  85. for (int i=0;i<len;i++) A[i]=A[i]*C[i];
  86. FFT(A,-1);
  87. Transfer(A);
  88. F(i,1,n) printf("%d ",T(A[i%n].x)); printf("\n");
  89. return 0;
  90. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注