洛谷P1919 【模板】A*B Problem升级版(FFT)

本文介绍如何使用快速傅立叶变换(FFT)算法进行大数乘法,通过将数字转换为多项式,利用FFT加速乘法过程,再通过逆FFT得到结果。文章包含详细的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

 

话说FFT该不会真的只能用来做这种板子吧……

我们把两个数字的每一位都看作多项式的系数

然后这就是一个多项式乘法

上FFT就好了

然后去掉前导零

(然而连FFT的板子都背不来orz,而且空间又开小了……)

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 using namespace std;
 6 char sr[1<<21],z[20];int C=-1,Z;
 7 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
 8 inline void print(int x){
 9     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
10     while(z[++Z]=x%10+48,x/=10);
11     while(sr[++C]=z[Z],--Z);
12 }
13 const int N=2e5+5;const double Pi=acos(-1.0);
14 int r[N],l=0,limit=1,c[N],n;char sa[N],sb[N];
15 struct complex{
16     double x,y;
17     complex(double xx=0,double yy=0){x=xx,y=yy;}
18     inline complex operator +(complex b){return complex(x+b.x,y+b.y);}
19     inline complex operator -(complex b){return complex(x-b.x,y-b.y);}
20     inline complex operator *(complex b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
21 }a[N],b[N];
22 void FFT(complex *a,int type){
23     for(int i=0;i<limit;++i)
24     if(i<r[i]) swap(a[i],a[r[i]]);
25     for(int mid=1;mid<limit;mid<<=1){
26         complex Wn(cos(Pi/mid),type*sin(Pi/mid));
27         for(int R=mid<<1,j=0;j<limit;j+=R){
28             complex w(1,0);
29             for(int k=0;k<mid;++k,w=w*Wn){
30                 complex x=a[j+k],y=w*a[j+k+mid];
31                 a[j+k]=x+y,a[j+k+mid]=x-y;
32             }
33         }
34     }
35 }
36 int main(){
37 //    freopen("testdata.in","r",stdin);
38     scanf("%d",&n),--n;
39     scanf("%s%s",sa,sb);
40     for(int i=0;i<=n;++i) a[i].x=sa[n-i]-'0',b[i].x=sb[n-i]-'0';
41     while(limit<=n*2) limit<<=1,++l;
42     for(int i=0;i<=limit;++i) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
43     FFT(a,1),FFT(b,1);
44     for(int i=0;i<=limit;++i) a[i]=a[i]*b[i];
45     FFT(a,-1);
46     for(int i=0;i<=limit;++i) c[i]=(int)(a[i].x/limit+0.5);
47     for(int i=0;i<=limit;++i)
48     if(c[i]>9){
49         c[i+1]+=c[i]/10,c[i]%=10;
50         if(i+1>limit) ++limit;
51     }
52     for(int i=limit;i>=0;--i)
53     if(c[i]==0) --limit;
54     else break;
55     for(int i=limit;i>=0;--i) print(c[i]);
56     Ot();
57     return 0;
58 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9742468.html

内容概要:该研究通过在黑龙江省某示范村进行24小时实地测试,比较了燃煤炉具与自动/手动进料生物质炉具的污染物排放特征。结果显示,生物质炉具相比燃煤炉具显著降低了PM2.5、CO和SO2的排放(自动进料分别降低41.2%、54.3%、40.0%;手动进料降低35.3%、22.1%、20.0%),但NOx排放未降低甚至有所增加。研究还发现,经济性和便利性是影响生物质炉具推广的重要因素。该研究不仅提供了实际排放数据支持,还通过Python代码详细复现了排放特征比较、减排效果计算和结果可视化,进一步探讨了燃料性质、动态排放特征、碳平衡计算以及政策建议。 适合人群:从事环境科学研究的学者、政府环保部门工作人员、能源政策制定者、关注农村能源转型的社会人士。 使用场景及目标:①评估生物质炉具在农村地区的推广潜力;②为政策制定者提供科学依据,优化补贴政策;③帮助研究人员深入了解生物质炉具的排放特征和技术改进方向;④为企业研发更高效的生物质炉具提供参考。 其他说明:该研究通过大量数据分析和模拟,揭示了生物质炉具在实际应用中的优点和挑战,特别是NOx排放增加的问题。研究还提出了多项具体的技术改进方向和政策建议,如优化进料方式、提高热效率、建设本地颗粒厂等,为生物质炉具的广泛推广提供了可行路径。此外,研究还开发了一个智能政策建议生成系统,可以根据不同地区的特征定制化生成政策建议,为农村能源转型提供了有力支持。
### 洛谷 FFT 题目与解法 洛谷平台上的 FFT(快速傅里叶变换)相关题目通常涉及多项式乘法、卷积计算以及字符串匹配等场景。以下是关于 FFT 的一些常见题型及解法的总结[^1]。 #### 1. 多项式乘法 FFT 最常见的应用之一是加速多项式的乘法运算。给定两个多项式 $A(x)$ 和 $B(x)$,直接相乘的时间复杂度为 $O(n^2)$,而使用 FFT 可以将时间复杂度优化到 $O(n \log n)$。以下是一个基于 FFT 的多项式乘法代码示例[^2]: ```cpp #include <iostream> #include <complex> #include <vector> using namespace std; typedef complex<double> cp; void FFT(vector<cp> &a, int n, int inv) { for(int i=0, j=0; i<n; ++i){ if(i > j) swap(a[i], a[j]); for(int k = n >> 1; (j ^= k) < k; k >>= 1); } for(int len=2; len<=n; len<<=1){ double ang = inv * 2 * acos(-1) / len; cp wlen(cos(ang), sin(ang)); for(int i=0; i<n; i+=len){ cp w(1, 0); for(int j=0; j<len/2; ++j){ cp u = a[i+j], v = a[i+j+len/2] * w; a[i+j] = u + v; a[i+j+len/2] = u - v; w *= wlen; } } } if(inv == -1){ for(auto &x : a) x /= n; } } vector<double> multiply(const vector<double> &a, const vector<double> &b){ int n = 1; while(n < (int)a.size() + (int)b.size()) n <<= 1; vector<cp> fa(a.begin(), a.end()), fb(b.begin(), b.end()); fa.resize(n); fb.resize(n); FFT(fa, n, 1); FFT(fb, n, 1); for(int i=0; i<n; ++i) fa[i] *= fb[i]; FFT(fa, n, -1); vector<double> res(n); for(int i=0; i<n; ++i) res[i] = fa[i].real(); return res; } ``` #### 2. 字符串匹配 FFT 还可以用于字符串匹配问题,例如通过将字符串转化为数值序列后进行卷积计算。以下是字符串匹配的一个简单实现[^2]: ```cpp #include <bits/stdc++.h> using namespace std; typedef complex<double> cp; const double PI = acos(-1); void fft(vector<cp> &a, bool inv){ int n = a.size(); for(int i=1,j=0;i<n-1;i++){ for(int k=n>>1;k>(j^=k);k>>=1); if(i<j) swap(a[i],a[j]); } for(int len=2;len<=n;len<<=1){ double ang = 2*PI/len*(inv?-1:1); cp wlen(cos(ang),sin(ang)); for(int i=0;i<n;i+=len){ cp w(1,0); for(int j=0;j<len/2;j++){ cp u = a[i+j], v = a[i+j+len/2]*w; a[i+j] = u+v; a[i+j+len/2] = u-v; w *= wlen; } } } if(inv){ for(auto &x:a) x/=n; } } int main(){ string s1,s2; cin >> s1 >> s2; int m = s1.size(), n = s2.size(); vector<cp> A(m), B(n); for(int i=0;i<m;i++) A[i] = s1[i]-'a'+1; for(int i=0;i<n;i++) B[i] = s2[i]-'a'+1; reverse(A.begin(), A.end()); int len = 1; while(len < m + n) len <<= 1; A.resize(len, 0); B.resize(len, 0); fft(A, false); fft(B, false); for(int i=0;i<len;i++) A[i] *= B[i]; fft(A, true); for(int i=m-1;i<n;i++) cout << fixed << setprecision(0) << A[i].real() << " "; } ``` #### 3. 洛谷 FFT 教程 洛谷平台上有一些高质量的 FFT 教程,例如《浅谈 FFT——从 DFT 到 FFT》[^1]。这篇教程详细介绍了 FFT 的数学原理、DFT 的定义以及如何用 FFT 加速多项式乘法。此外,还提供了丰富的代码示例和实际应用场景。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值