[关闭]
@xunuo 2017-01-20T09:40:35.000000Z 字数 3406 阅读 946

A * B Problem Plus


Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

FFT

来源:HDU 1402 A * B Problem Plus


Description

Calculate A * B.

Input

Each line will contain two integers A and B. Process to end of file.

Note: the length of each integer will not exceed 50000.

Output

For each case, output A * B in one line.

Sample Input

1
2
1000
2

Sample Output

2
2000

题意:

输入两个数,输出他们的乘积

解题思路:

如果用高精度会超时......
用FFT或者NTT......
然而你啥都不知道~~呵呵哒

完整代码:

  1. ///这个是张晓雨学长的FFT模板
  2. #include<stdio.h>
  3. #include<math.h>
  4. #include<complex>
  5. #include<string.h>
  6. #include<algorithm>
  7. using namespace std;
  8. #define maxn 400000
  9. const double PI=acos(-1.0);
  10. typedef complex <double> Complex;
  11. void rader(Complex *y, int len)
  12. {
  13. for(int i=1,j=len/2;i<len-1;i++)
  14. {
  15. if(i<j)
  16. swap(y[i],y[j]);
  17. int k=len/2;
  18. while(j>=k)
  19. {
  20. j-=k;
  21. k/=2;
  22. }
  23. if(j<k)j+=k;
  24. }
  25. }
  26. void fft(Complex *y,int len,int op)
  27. {
  28. rader(y,len);
  29. for(int h=2;h<=len;h<<=1)
  30. {
  31. double ang=op*2*PI/h;
  32. Complex wn(cos(ang),sin(ang));
  33. for(int j=0;j<len;j+=h)
  34. {
  35. Complex w(1,0);
  36. for(int k=j;k<j+h/2;k++)
  37. {
  38. Complex u=y[k];
  39. Complex t=w*y[k+h/2];
  40. y[k]=u+t;
  41. y[k+h/2]=u-t;
  42. w=w*wn;
  43. }
  44. }
  45. }
  46. if(op==-1)
  47. for(int i=0;i<len;i++)
  48. y[i]/=len;
  49. }
  50. Complex x1[maxn], x2[maxn];
  51. char str1[maxn], str2[maxn];
  52. int sum[maxn];
  53. int main()
  54. {
  55. while(scanf("%s%s",str1,str2)!=EOF)
  56. {
  57. int len1=strlen(str1);
  58. int len2=strlen(str2);
  59. int len=1;
  60. while(len<len1*2||len<len2*2)
  61. len<<=1;
  62. for(int i=0;i<len1;i++)
  63. x1[i]=Complex(str1[len1-1-i]-'0',0);
  64. for(int i=len1;i<len;i++)
  65. x1[i]=Complex(0,0);
  66. for(int i=0;i<len2;i++)
  67. x2[i]=Complex(str2[len2-i-1]-'0',0);
  68. for(int i=len2;i<len;i++)
  69. x2[i]=Complex(0,0);
  70. //DFT
  71. fft(x1,len,1);
  72. fft(x2,len,1);
  73. for(int i=0;i<len;i++)
  74. x1[i]=x1[i]*x2[i];
  75. fft(x1,len,-1);
  76. for(int i=0;i<len;i++)
  77. sum[i]=(int)(x1[i].real()+0.5);
  78. for(int i=0;i<len;i++)
  79. {
  80. sum[i+1]+=sum[i]/10;
  81. sum[i]%=10;
  82. }
  83. len=len1+len2-1;
  84. while(sum[len]<=0&&len>0)
  85. len--;
  86. for(int i=len;i>=0;i--)
  87. printf("%c",sum[i]+'0');
  88. printf("\n");
  89. }
  90. return 0;
  91. }

这个是阳哥的NTT

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cmath>
  4. #include<algorithm>
  5. #define MAXN 400000
  6. #define LL long long
  7. const LL P = (479 << 21) + 1;//费马素数P
  8. const LL G = 3;//P的原根 只有G的P-1次方等于1,G的i次方(0<=i<P-1)都不为1。
  9. //P = (119 << 23) +1;G=3
  10. //P = (1917 << 19)+1;G=5
  11. //P = (453 << 21 )+1 G=7
  12. #define NUM 20 //2的20次方大于MAXN
  13. LL Wn[NUM];
  14. using namespace std;
  15. LL quickly_mod(LL a, LL n, LL mod)
  16. {
  17. LL res = 1, tmp = a;
  18. while (n)
  19. {
  20. if (n & 1)
  21. {
  22. res *= tmp;
  23. res %= mod;
  24. }
  25. tmp *= tmp;
  26. tmp %= mod;
  27. n >>= 1;
  28. }
  29. return res;
  30. }
  31. void getWn()
  32. {
  33. for (int i = 0; i < NUM; i++)
  34. {
  35. int t = 1 << i;
  36. Wn[i] = quickly_mod(G, (P - 1) / t, P);
  37. }
  38. }
  39. inline int turn(int n)
  40. {
  41. int i = 1;
  42. for (; i < n; i <<= 1);
  43. return i;
  44. }
  45. void build(LL _S[], LL S[], int n, int m, int curr, int &cnt)
  46. {
  47. if (m == n) _S[curr] = S[cnt++];
  48. else
  49. {
  50. build(_S, S, n, m << 1, curr, cnt);
  51. build(_S, S, n, m << 1, curr + m, cnt);
  52. }
  53. }
  54. void NTT(LL S[], int n, int op)
  55. {
  56. static LL _S[MAXN];
  57. int cnt = 0;
  58. build(_S, S, n, 1, 0, cnt);
  59. memcpy(S, _S, sizeof(LL)*n);
  60. for (int len = 2, id = 1; len <= n; len <<= 1, id++)
  61. {
  62. int m = len >> 1;
  63. LL unit = Wn[id];
  64. for (int i = 0; i < n; i += len)
  65. {
  66. LL W = 1;
  67. for (int j = 0; j < m; j++, W = W*unit%P)
  68. {
  69. LL p = S[i + j], q = S[i + j + m];
  70. S[i + j] = (p + W*q) % P;
  71. S[i + j + m] = ((p - W*q) % P + P) % P;
  72. }
  73. }
  74. }
  75. if (op == -1)
  76. {
  77. for (int i = 1; i < (n >> 1); i++)
  78. swap(S[i], S[n - i]);
  79. LL INV = quickly_mod(n, P - 2, P);
  80. for (int i = 0; i < n; i++)
  81. S[i] = S[i] * INV % P; //除以N----INV是逆元
  82. }
  83. }
  84. LL A[MAXN], B[MAXN];
  85. char s[MAXN];
  86. int ans[MAXN];
  87. int main()
  88. {
  89. getWn();
  90. while (~scanf("%s", s))
  91. {
  92. int n = 0;
  93. memset(A, 0, sizeof(A));
  94. memset(B, 0, sizeof(B));
  95. int len = strlen(s);
  96. n = len;
  97. for (int i = 0; i < len; i++)
  98. A[i] = s[len - i - 1] - 48;
  99. scanf("%s", s);
  100. len = strlen(s);
  101. for (int i = 0; i < len; i++)
  102. B[i] = s[len - i - 1] - 48;
  103. n = len > n ? len : n;
  104. n = turn(n);
  105. NTT(A, n << 1, 1);
  106. NTT(B, n << 1, 1);
  107. for (int i = 0; i < (n << 1); i++)
  108. A[i] = (A[i] * B[i])%P;
  109. NTT(A, n << 1, -1);
  110. memset(ans, 0, sizeof(ans));
  111. for (int i = 0; i < (n << 1); i++)
  112. ans[i] = A[i];
  113. for (int i = 0; i < (n << 1); i++)
  114. {
  115. ans[i + 1] += ans[i] / 10;
  116. ans[i] %= 10;
  117. }
  118. for (len = n << 1; len > 0 && !ans[len]; len--);
  119. for (; len >= 0; len--)
  120. putchar(ans[len] + 48);
  121. printf("\n");
  122. }
  123. return 0;
  124. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注