zoukankan      html  css  js  c++  java
  • hdu1402(大数a*b&fft模板)

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

    题意: 给出两个长度1e5以内的大数a, b, 输出 a * b.

    思路: fft模板

    详情参见:  m.blog.csdn.net/f_zyj/article/details/76037583

           http://blog.csdn.net/sdj222555/article/details/9786527

          https://wenku.baidu.com/view/8bfb0bd476a20029bd642d85.html

    可以将 a, b 看成两个多项式, 每个数位为一项, 每一位上的数字即为所在项的系数.所以直接fft即可.

    代码:

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <math.h>
      4 #include <string.h>
      5 #include <stdio.h>
      6 using namespace std;
      7 
      8 const double PI = acos(-1.0);
      9 
     10 struct Complex{//复数结构体
     11     double x, y;//实部,虚部
     12     Complex(double _x = 0.0, double _y = 0.0){
     13         x = _x;
     14         y = _y;
     15     }
     16     Complex operator -(const Complex &b) const{
     17         return Complex(x - b.x, y - b.y);
     18     }
     19     Complex operator +(const Complex &b) const{
     20         return Complex(x + b.x, y + b.y);
     21     }
     22     Complex operator *(const Complex &b) const{
     23         return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
     24     }
     25 };
     26 
     27 //进行FFT和IFFT反转变化
     28 //位置i和(i二进制反转后位置)互换
     29 void change(Complex y[], int len){//len必须为2的幂
     30     for(int i = 1, j = len / 2; i < len - 1; i++){
     31         if(i < j) swap(y[i], y[j]); //交换互为下标反转的元素,i<j保证只交换一次
     32         int k = len >> 1;
     33         while(j >= k){
     34             j -= k;
     35             k /= 2;
     36         }
     37         if(j < k) j += k;
     38     }
     39 }
     40 
     41 //做FFT,len必须为2的幂,on=1是DFT,on=-1是IDTF
     42 void fft(Complex y[], int len, int on){
     43     change(y, len);//调用反转置换
     44     for(int h = 2; h <= len; h <<= 1){
     45         Complex wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h));
     46         for(int j = 0; j < len; j += h){
     47             Complex w(1, 0);//初始化螺旋因子
     48             for(int k = j; k < j + h / 2; k++){//配对
     49                 Complex u = y[k];
     50                 Complex t = w * y[k + h / 2];
     51                 y[k] = u + t;
     52                 y[k + h / 2] = u - t;
     53                 w = w * wn;//更新螺旋因子
     54             }
     55         }
     56     }
     57     if(on == -1){
     58         for(int i = 0; i < len; i++){
     59             y[i].x /= len;//IDTF
     60         }
     61     }
     62 }
     63 
     64 const int MAXN = 2e5 + 10;
     65 Complex x1[MAXN], x2[MAXN];
     66 char str1[MAXN >> 1], str2[MAXN >> 1];
     67 int sum[MAXN];
     68 
     69 int main(void){
     70     while(~scanf("%s%s", str1, str2)){
     71         int len1 = strlen(str1);
     72         int len2 = strlen(str2);
     73         int len = 1;
     74         while(len < len1 * 2 || len < len2 * 2) len <<= 1;
     75         //将str1,str2构造成两个多项式
     76         for(int i = 0; i < len1; i++){//倒存
     77             x1[i] = Complex(str1[len1 - i - 1] - '0', 0);
     78         }
     79         for(int i = len1; i < len; i++){
     80             x1[i] = Complex(0, 0);//不够的补0
     81         }
     82         for(int i = 0; i < len2; i++){
     83             x2[i] = Complex(str2[len2 - i - 1] - '0', 0);
     84         }
     85         for(int i = len2; i < len; i++){
     86             x2[i] = Complex(0, 0);
     87         }
     88         fft(x1, len, 1); //DFT(str1)
     89         fft(x2, len, 1); //DFT(str2);
     90         for(int i = 0; i < len; i++){
     91             x1[i] = x1[i] * x2[i];//点乘结果存入x1
     92         }
     93         fft(x1, len, -1);//IDFT(a*b)
     94         for(int i = 0; i < len; i++){
     95             sum[i] = (int)(x1[i].x + 0.5);//四舍五入
     96         }
     97         for(int i = 0; i < len; i++){
     98             sum[i + 1] += sum[i] / 10;
     99             sum[i] %= 10;
    100         }
    101         len = len1 + len2 - 1;//长度为len1和len2的两个数的乘积长度最大不超过len1+len2+1
    102         while(sum[len] <= 0 && len > 0) len--;//去前导0
    103         for(int i = len; i >= 0; i--){
    104             printf("%d", sum[i]);
    105         }
    106         puts("");
    107     }
    108     return 0;
    109 }
    View Code
  • 相关阅读:
    /dev/sdxx is apparently in use by the system; will not make a filesystem here! 解决方法
    device mapper的使用
    linux中挂载硬盘报错(you must specify the filesystem type)
    Linux系统分区方案建议
    正确配置Linux系统ulimit值的方法
    ulimit -c unlimited
    ulimit -n 修改
    修改Linux内核参数,减少TCP连接中的TIME-WAIT
    sysctl -P 报错解决办法
    linux 内核参数调整优化网络
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7512218.html
Copyright © 2011-2022 走看看