zoukankan      html  css  js  c++  java
  • [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         //进位
     93         for(int i = 0; i < n; i++) {
     94             sum[i+1] += sum[i] / 10;
     95             sum[i] %= 10;
     96         }
     97         n = na + nb - 1;
     98         while(sum[n] <= 0 && n > 0) n--;
     99         for(int i = n; i >= 0; i--) printf("%c", sum[i]+'0');
    100         printf("
    ");
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    二分法查找(C语言)
    冒泡排序法(C语言)
    Python 字符串操作方法大全
    guns搭建笔记
    mysql数据库下载及安装
    docker安装
    自动化学习路径及问题汇总目录
    UI自动化使用docker做并行执行
    allure趋势图无数据
    allure报告不显示@Attachment
  • 原文地址:https://www.cnblogs.com/kirai/p/6129845.html
Copyright © 2011-2022 走看看