[HDU1402]A * B Problem Plus(FFT)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1402

题意:大数乘法。

数太大,O(n^2)的不行,得用fft对乘法加速。

手推了一遍FFT的公式,感觉欧拉和分治很强,纪念我的第一发FFT。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3
  4 const double PI = acos(-1.0);
  5 //复数结构体
  6 typedef struct Complex {
  7     double r,i;
  8     Complex(double _r = 0.0,double _i = 0.0) {
  9         r = _r; i = _i;
 10     }
 11     Complex operator +(const Complex &b) {
 12         return Complex(r+b.r,i+b.i);
 13     }
 14     Complex operator -(const Complex &b) {
 15         return Complex(r-b.r,i-b.i);
 16     }
 17     Complex operator *(const Complex &b) {
 18         return Complex(r*b.r-i*b.i,r*b.i+i*b.r);
 19     }
 20 }Complex;
 21 /*
 22  * 进行FFT和IFFT前的反转变换。
 23  * 位置i和 (i二进制反转后位置)互换
 24  * len必须是2的幂
 25  */
 26 void change(Complex y[],int len) {
 27     int i,j,k;
 28     for(i = 1, j = len/2;i < len-1; i++) {
 29         if(i < j)swap(y[i],y[j]);
 30         //交换互为小标反转的元素,i<j保证交换一次
 31         //i做正常的+1,j左反转类型的+1,始终保持i和j是反转的
 32         k = len/2;
 33         while( j >= k) {
 34             j -= k;
 35             k /= 2;
 36         }
 37         if(j < k) j += k;
 38     }
 39 }
 40 /*
 41  * 做FFT
 42  * len必须为2^k形式,
 43  * on==1时是DFT,on==-1时是IDFT
 44  */
 45 void fft(Complex y[],int len,int on) {
 46     change(y,len);
 47     for(int h = 2; h <= len; h <<= 1) {
 48         Complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
 49         for(int j = 0;j < len;j+=h) {
 50             Complex w(1,0);
 51             for(int k = j;k < j+h/2;k++) {
 52                 Complex u = y[k];
 53                 Complex t = w*y[k+h/2];
 54                 y[k] = u+t;
 55                 y[k+h/2] = u-t;
 56                 w = w*wn;
 57             }
 58         }
 59     }
 60     if(on == -1) {
 61         for(int i = 0;i < len;i++) {
 62             y[i].r /= len;
 63         }
 64     }
 65 }
 66
 67 const int maxn = 200200;
 68 char ta[maxn], tb[maxn];
 69 int na, nb;
 70 Complex a[maxn], b[maxn];
 71 int n;
 72 int sum[maxn];
 73
 74 int main() {
 75     // freopen("in", "r", stdin);
 76     while(~scanf("%s%s",ta, tb)) {
 77         na = strlen(ta); nb = strlen(tb); n = 1;
 78         while(n < na * 2 || n < nb * 2) n <<= 1;
 79         // 搞成多项式的形式
 80         for(int i = 0; i < na; i++) a[i] = Complex(ta[na-1-i]-‘0‘, 0);
 81         for(int i = na; i < n; i++) a[i] = Complex(0, 0);
 82         for(int i = 0; i < nb; i++) b[i] = Complex(tb[nb-1-i]-‘0‘, 0);
 83         for(int i = nb; i < n; i++) b[i] = Complex(0, 0);
 84         // fft转换成用点值表达两个数
 85         fft(a, n, 1); fft(b, n, 1);
 86         // 性质:自变量相同的情况下,求两个函数值的乘积,直接乘起来就行了
 87         for(int i = 0; i < n; i++) a[i] = a[i] * b[i];
 88         // 求逆DFT,也就是再转换成系数表达
 89         fft(a, n, -1);
 90         // 四舍五入,日掉精度的问题
 91         for(int i = 0; i < n; i++) sum[i] = (int)(a[i].r + 0.5);
 92         for(int i = 0; i < n; i++) {
 93             sum[i+1] += sum[i] / 10;
 94             sum[i] %= 10;
 95         }
 96         n = na + nb - 1;
 97         while(sum[n] <= 0 && n > 0) n--;
 98         for(int i = n; i >= 0; i--) printf("%c", sum[i]+‘0‘);
 99         printf("\n");
100     }
101     return 0;
102 }
时间: 2024-11-10 15:06:16

[HDU1402]A * B Problem Plus(FFT)的相关文章

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)Total Submission(s): 12665    Accepted Submission(s): 2248 Problem Description Calculate A * B. Input Each line will contain two integers A and B. P

P1919 【模板】A*B Problem升级版(FFT快速傅里叶)

P1919 [模板]A*B Problem升级版(FFT快速傅里叶) 思路还是挺简单的. 输入的2个数 \(a=\overline{a_n a_{n-1} a_{n-2}\cdots a_{0}}\) , \(b=\overline{b_m b_{m-1} b_{m-2}\cdots b_{0}}\) 直接把 \(a_i\) 和 \(b_i\) 看做多项式 A 和 B 的系数,做多项式乘法即可.因为 a ,b 可以看做以 \(a_i,b_i\) 为系数,自变量为10的多项式的值,乘完后的多项式的

Hdu 1402 (FFT)

题目链接 A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 12490    Accepted Submission(s): 2206 Problem Description Calculate A * B. Input Each line will contain two integers A and

HDU1022 Train Problem I (栈)

栈+队列 1 #include<stdio.h> 2 #include<string.h> 3 #include<stack> 4 #include<queue> 5 using namespace std; 6 int main() 7 { 8 int n; 9 char a[11],b[11]; 10 stack<char>s; 11 queue<int>q; 12 while(scanf("%d",&

BZOJ 2298 problem a(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2298 题意:一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低.”问最少有几个人没有说真话(可能有相同的分数) 思路:对于第i个人来说,区间[ai+1,n-bi]的人的分数相同.那么我们用sum[L][R]表示区间[L,R]中总人数.用f[i]表示前i个人中说真话的最大人数,那么f[j]=max(f[i-1]+sum[i][j]). map<pair<in

快速傅里叶变换(FFT)

快速傅里叶变换(FFT)算法[详解] 快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.我打开一本老旧的算法书,欣赏了JW Cooley 和 John Tukey 在1965年的文章中,以看似简单的计算技巧来讲解这个东西. 本文的目标是,深入Cooley-Tukey  FFT 算法,解释作为其根源的"对称性",并以一些直观的python代码将其理论转变为实际.我希望这次研究能对这个算法的背景原理有更全面的认识. FFT(快速傅里叶

You can Solve a Geometry Problem too (hdu1086)几何,判断两线段相交

You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6837 Accepted Submission(s): 3303 Problem Description Many geometry(几何)problems were designed in the ACM/ICPC. A

洛谷P3803 【模板】多项式乘法(FFT)

P3803 [模板]多项式乘法(FFT) 题目背景 这是一道FFT模板题 题目描述 给定一个n次多项式F(x),和一个m次多项式G(x). 请求出F(x)和G(x)的卷积. 输入输出格式 输入格式: 第一行2个正整数n,m. 接下来一行n+1个数字,从低到高表示F(x)的系数. 接下来一行m+1个数字,从低到高表示G(x))的系数. 输出格式: 一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数. 输入输出样例 输入样例#1: 复制 1 2 1 2 1 2 1 输出样例#1: 复制 1

BZOJ[3527],[ZJOI2014]力(FFT)

BZOJ[3527],[ZJOI2014]力(FFT) 题意: 给出\(n\)个数\(q_i\),给出\(Fj\)的定义如下: \(F_j=\sum \limits _ {i < j} \frac{q_iq_j}{(i-j)^2}-\sum \limits _{i >j} \frac{q_iq_j}{(i-j)^2}.\) 令\(E_i=F_i/q_i\),求\(E_i\). 题解: 一开始没发现求\(E_i\)... 其实题目还更容易想了... \(E_i=\sum\limits _{j&l