HDU 1402 fft 模板题

题目就是求一个大数的乘法

这里数字的位数有50000的长度,按平时的乘法方式计算,每一位相乘是要n^2的复杂度的,这肯定不行

我们可以将每一位分解后作为系数,如153 = 1*x^2 + 5*x^1 + 3*x^0 (在这里x可以理解成10)

那么两个数字相乘就相当于系数相乘后得到新的系数组合

如153 * 4987 = <3,5,1> * <7,8,9,4>

这相当于卷积的计算,最快的方式就是fft,nlgn的复杂度就能求解,求解得到后再把每一位大于10往前赋值就行了

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <math.h>
  6
  7 using namespace std;
  8 const double PI = acos(-1.0);
  9
 10 struct complex{
 11     double r , i;
 12     complex(double r=0 , double i=0):r(r),i(i){}
 13     complex operator+(const complex &a) const{
 14         return complex(r+a.r , i+a.i);
 15     }
 16     complex operator-(const complex &a) const{
 17         return complex(r-a.r , i-a.i);
 18     }
 19     complex operator*(const complex &a) const{
 20         return complex(r*a.r-i*a.i , r*a.i+i*a.r);
 21     }
 22 };
 23
 24 void change(complex y[] , int len)
 25 {
 26     int i,j,k;
 27     for(i=1 , j=len/2 ; i<len-1 ; i++){
 28         if(i<j) swap(y[i],y[j]);
 29         k = len/2;
 30         while(j>=k){
 31             j-=k;
 32             k/=2;
 33         }
 34         if(j<k) j+=k;
 35     }
 36 }
 37
 38 void fft(complex y[] , int len , int on)
 39 {
 40     change(y , len);
 41     for(int i=2 ; i<=len ; i<<=1){
 42         complex wn(cos(-on*2*PI/i) , sin(-on*2*PI/i));
 43         for(int j=0 ; j<len ; j+=i){
 44             complex w(1,0);
 45             for(int k=j ; k<j+i/2 ; k++){
 46                 complex u = y[k];
 47                 complex t = w*y[k+i/2];
 48                 y[k] = u+t;
 49                 y[k+i/2] = u-t;
 50                 w = w*wn;
 51             }
 52         }
 53     }
 54     if(on==-1)
 55         for(int i=0 ; i<len ; i++)
 56             y[i].r /= len;
 57
 58 }
 59
 60 const int MAXN = 200010;
 61 complex x1[MAXN] , x2[MAXN];
 62 char str1[MAXN] , str2[MAXN];
 63 int sum[MAXN];
 64
 65 int main()
 66 {
 67     while(~scanf("%s%s" , str1 , str2)){
 68         int len1 = strlen(str1) , len2 = strlen(str2);
 69         int len = 1;
 70         //fft的计算,由于是倍增的,需要保证是2^k次方,且要大于最后得到的结果的总位数
 71         while(len<len1*2 || len<len2*2) len<<=1;
 72         for(int i=0 ; i<len1 ; i++)
 73             x1[i] = complex(str1[len1-1-i]-‘0‘ , 0);
 74         for(int i=len1 ; i<len ; i++)
 75             x1[i] = complex(0 , 0);
 76         for(int i=0 ; i<len2 ; i++)
 77             x2[i] = complex(str2[len2-1-i]-‘0‘ , 0);
 78         for(int i=len2 ; i<len ; i++)
 79             x2[i] = complex(0 , 0);
 80         //将当前的组合数的系数值修改成复数坐标系的点值o(nlgn)
 81         fft(x1 , len , 1);
 82         fft(x2 , len , 1);
 83         //点值可以o(n)的时间内进行计算
 84         for(int i=0 ; i<len ; i++)
 85             x1[i] = x1[i]*x2[i];
 86         //将点值重新通过逆过程(又叫dft)转化为系数值
 87         fft(x1 , len , -1);
 88
 89         memset(sum , 0 , sizeof(sum));
 90         for(int i=0 ; i<len ; i++) sum[i] = (int)(x1[i].r+0.5);
 91         for(int i=0 ; i<len ; i++){
 92             sum[i+1] += sum[i]/10;
 93             sum[i] = sum[i]%10;
 94         }
 95         int ansl = len1+len2-1;
 96         while(sum[ansl]==0 && ansl>0) ansl--;
 97         for(int i=ansl ; i>=0 ; i--) printf("%c" , sum[i]+‘0‘);
 98         printf("\n");
 99     }
100     return 0;
101 }
时间: 2024-08-28 06:40:10

HDU 1402 fft 模板题的相关文章

Saving Princess claire_(hdu 4308 bfs模板题)

http://acm.hdu.edu.cn/showproblem.php?pid=4308 Saving Princess claire_ Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2305    Accepted Submission(s): 822 Problem Description Princess claire_ wa

hdu 1711 KMP模板题

// hdu 1711 KMP模板题 // 贴个KMP模板吧~~~ #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; const int MAX_N = 1000008; const int MAX_M = 10008; int T[MAX_N]; int p[MAX_M]; int f[MAX_M]; int

hdu 2586 LCA模板题(离线算法)

http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B&quo

A * B Problem Plus HDU - 1402 (FFT)

A * B Problem Plus HDU - 1402 第一道FFT... 1 #include <iostream> 2 #include <complex> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 9 const int maxn = 200010; 1

HDU 2586 LCA模板题

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目大意:在一个无向树上,求一条链权和. 解题思路: 0 | 1 /   \ 2      3 设dist[i]为i到根0的链和,求法(Dfs过程中dist[v]=dist[u]+e[i].w) 对于树中任意两点形成的链,可以通过LCA最近公共祖先剖分. 比如2->3,就可以经过LCA点1:  2->1->3 链和=dist[u]+dist[v]-2*dist[LCA[u,v]] (

hdu 2544 hdu 1874 Dijkstra 模板题

hdu 2544  求点1到点n的最短路 Sample Input2 1 //结点数 边数1 2 3 //u v w3 31 2 52 3 53 1 20 0 Sample Output32 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # define LL long

HDU 2087 kmp模板题

s为主串 t为模板串 求t的nextt 加const #include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<math.h> #include<queue> using namespace std; char s[1005]; char t[1005]; int nextt[1005]; void makenext(const ch

【网络流#3】hdu 1532 - Dinic模板题

输入为m,n表示m条边,n个结点 记下来m行,每行三个数,x,y,c表示x到y的边流量最大为c 这道题的模板来自于网络 http://blog.csdn.net/sprintfwater/article/details/7913061 建议大家去这个页面看看,博主也很良心地添加了很多注释 关于这个模板:Edge为前向星的边数,所以需要初始化Edge和head数组 n表示有n个点,这个版无所谓点从0开始还是从1开始,s表示源点,t表示汇点很好的一个是,这个版的DFS使用的是模拟栈,防止爆栈 1 #

hdu 1423 GCIS 模板题

//GCIS 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 using namespace std; 6 int dp[510], Max; 7 int s1[510], s2[510]; 8 int len1, len2; 9 10 int main() 11 { 12 int T, i, j;