0%

HDU 1402 A * B Problem Plus 快速高精度乘法(FFT)

A * B Problem Plus

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

Problem 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

题意

做两个超大数的乘法,每个数极限是50000位,略大,一般普通的模拟高精会超时

分析

普通的模拟高精是$O(n^2)$的复杂度,对于这种特殊的50000长的数据自然是会超了的

故本题的解法就是借用FFT加速的高精度乘法,复杂度在$O(nlogn)$

FFT的详细分析在上一篇中已经讲清楚了,本题即作为模板题

我的模板是在原来自己搞的高精的基础上改的,最初的高精用了4位押位,然而套上这个之后,发现FFT中间的结果大小跟位数也有关,当位数大到一定程度的时候,4位押位在int下会爆。。。然后50000位的极限数据在3位押位下都会爆int。。。好可怕

最后改到2位押位。

大概是我原本的输入输出部分模板写的不好,网上找的参考代码能在100ms以内过,我的这个需要花700ms左右。。。(捂脸)

下次用的时候考虑是不是需要套原本的高精模板,还有要注意押位的位数问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : FFT_HDU_1402
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

#define nn 70000
#define snn 60000

using namespace std;

struct gjtype
{
int a[nn];
void clean()
{
memset(a,0,sizeof(a));
}
void ntog(long long s)
{
clean();
int i=0;
while (s>0)
{
i++;
a[i]=s%100;
s=s/100;
}
a[0]=i;
}
void stog(char s1[])
{
clean();
char ss[snn],s[snn];
bool pos=true;
if (s1[0]=='-')
{
strcpy(s,s1+1);
pos=false;
} else strcpy(s,s1);
int i=0;
while (strlen(s)>=2)
{
i++;
for (int j=strlen(s)-2;j<strlen(s);j++)
ss[j-strlen(s)+2]=s[j];
s[strlen(s)-2]='\0';
a[i]=atoi(ss);
}
if (strlen(s)>0)
{
i++;
a[i]=atoi(s);
}
a[0]=i;
if (!pos) a[a[0]]=-a[a[0]];
}
void out()
{
printf("%d",a[a[0]]);
for (int i=a[0]-1;i>=1;i--)
printf("%02d",a[i]);
putchar('\n');
}
};
gjtype a,b,c;

const double PI = acos(-1.0);

struct fstype
{
double x,y;
fstype(double real = 0.0,double imag = 0.0)
{
x = real;
y = imag;
}
fstype operator -(const fstype &b)const
{
return fstype(x-b.x,y-b.y);
}
fstype operator +(const fstype &b)const
{
return fstype(x+b.x,y+b.y);
}
fstype operator *(const fstype &b)const
{
return fstype(x*b.x-y*b.y,x*b.y+y*b.x);
}
};

void fft(fstype y[],int len,int on)
{
int i,j,k;
for(i = 1, j = len/2;i <len-1;i++)
{
if (i < j) swap(y[i],y[j]);

k = len/2;
while(j >= k)
{
j -= k;
k /= 2;
}
if(j < k) j += k;
}

for(int h = 2; h <= len; h <<= 1)
{
fstype wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
for(int j = 0;j < len;j+=h)
{
fstype w(1,0);
for(int k = j;k < j+h/2;k++)
{
fstype u = y[k];
fstype t = w*y[k+h/2];
y[k] = u+t;
y[k+h/2] = u-t;
w = w*wn;
}
}
}

if(on == -1)
for(int i = 0;i < len;i++)
y[i].x /= len;
}

fstype x1[nn],x2[nn];
gjtype cc;

gjtype fftcheng(gjtype aa,gjtype bb)
{
int len1=aa.a[0],len2=bb.a[0],len=1;

while (len<len1*2||len<len2*2) len<<=1;

for (int i=1;i<=len1;i++) x1[i-1]=fstype(aa.a[i],0);
for (int i=len1;i<len;i++) x1[i]=fstype(0,0);

for (int i=1;i<=len2;i++) x2[i-1]=fstype(bb.a[i],0);
for (int i=len2;i<len;i++) x2[i]=fstype(0,0);

fft(x1,len,1);
fft(x2,len,1);

for (int i=0;i<len;i++) x1[i]=x1[i]*x2[i];

fft(x1,len,-1);

cc.clean();

for (int i=0;i<len;i++) cc.a[i+1]=(int)(x1[i].x+0.5);
for (int i=1;i<=len;i++)
{
cc.a[i+1]+=cc.a[i]/100;
cc.a[i]%=100;
}

while(cc.a[len] == 0 && len > 1)len--;

cc.a[0]=len;

return cc;
}

int main()
{
//freopen("1.txt","r",stdin);
//freopen("1.out","w",stdout);

gjtype a,b,c;

char s1[snn],s2[snn];

while (scanf("%s%s",s1,s2)!=EOF)
{
a.stog(s1);
b.stog(s2);

c=fftcheng(a,b);
c.out();

//c=cheng(a,b);
//c.out();
}

return 0;
}