题意:
给定两个\(\sqrt {-2}\)进制数,求他们的乘积。
思路:
首先不要去考虑\(\sqrt {-2}\),而是将它作为一个未知数\(x\)。那么我们要求的是两个关于\(x\)的多项式的乘积。很自然地想到FFT。然后我们能够得到一个多项式,考虑如何去将它还原成\(\sqrt {-2}\)进制数。
根据定义,我们发现每一项的系数都是\(1\)或\(0\),且\({(\sqrt {-2})}^2=-2\)。那么从小往大枚举,若当前第\(i\)项系数不为\(1\)或\(0\),设为\(x\cdot {(\sqrt {-2})}^i\),则我们根据\(x\)的奇偶,取出\(2k\cdot {(\sqrt {-2})}^i\)使得当前第\(i\)项系数满足\(1\)或\(0\),剩下部分\(2k\cdot {(\sqrt {-2})}^i=-k\cdot {(\sqrt {-2})}^{i+2}\),直接加到第\(i+2\)项系数上,整体过程类似进位。
整体时间复杂度就是FFT的复杂度\(O(nlogn)\).
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
constexpr int M=2e6+5e3;
const double pie=acos(-1.0);
struct comp{// 手打复数,避免被卡(其实一般也没有人来卡这个吧)。
double real,img;
comp(double xx=0,double yy=0){
real=xx;
img=yy;
}
comp operator + (const comp b)const{
return comp(real+b.real , img+b.img);
}
comp operator - (const comp b)const{
return comp(real-b.real , img-b.img);
}
comp operator * (const comp b)const{
return comp(real*b.real-img*b.img , real*b.img+img*b.real);
}
}f[M],g[M];
int n,m,l,lim=1;
int r[M];
void fft(comp *F,int oper){// oper 是操作,传入 1 是FFT,-1 是 IFFT。
for(int i=0;i<lim;i++){
if(i>r[i]-1){
continue;
}
swap(F[i],F[r[i]]);
}
for(int mid=1;mid<lim;mid<<=1){
comp wn(cos(pie/mid),oper*sin(pie/mid));
for(int R=mid<<1,j=0;j<lim;j+=R){
comp w(1.0,0.0);
for(int k=0;k<mid;k++,w=w*wn){
comp y=F[j+k],z=w*F[j+mid+k];
F[j+k]=y+z;
F[j+mid+k]=y-z;
}
}
}
}
string s1,s2;
int a[M];
void solve(){
cin>>s1>>s2;
n=s1.size()-1;
m=s2.size()-1;
for(int i=0;i<=(n+m)*2+2;i++){
a[i]=r[i]=0;
f[i]=g[i]={0,0};
}
for(int i=0;i<=n;i++){
f[i].real=s1[n-i]-'0';
}
for(int i=0;i<=m;i++){
g[i].real=s2[m-i]-'0';
}
lim=1;
l=0;
while(lim<n+m+1){
lim<<=1;
l++;
}
for(int i=0;i<lim;i++){
r[i]=((r[i>>1]>>1)|((i&1)<<(l-1)));
}
fft(f,1);
fft(g,1);
for(int i=0;i<lim;i++){
f[i]=f[i]*g[i];
}
fft(f,-1);
int len=n+m+1;
for(int i=0;i<len;i++){
if(i<n+m+1)a[i]+=(int)(f[i].real/lim+0.5);
if(a[i]>1){
a[i+2]-=a[i]/2;
a[i]%=2;
if(i+2>=len){
len=i+3;
}
}else if(a[i]<0){
int t=(-a[i]+1)/2;
a[i+2]+=t;
a[i]=(-a[i])%2;
if(i+2>=len){
len=i+3;
}
}
}
while (a[len] == 0 && len > 0) len--;
for (int i = len; i >= 0; i--) cout << a[i];
cout<<"\n";
}
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
int t = 1;
// freopen("in.txt", "r", stdin);
cin >> t;
while (t--) {
solve();
}
return 0;
}