1 条题解
-
0
说明
本题要求解密由TN设计的加密方案。给定两个实数序列β和γ,其中γ是通过特定的加密步骤从α和β生成的。我们的目标是恢复原始序列α。加密过程涉及将β反转、旋转后与α进行卷积运算。解密过程需要逆向操作,利用快速傅里叶变换(FFT)来高效求解。
算法标签
- 快速傅里叶变换(FFT):用于高效计算卷积和逆卷积
- 复数运算:处理实数序列的变换
- 数学推导:理解加密和解密的数学关系
解题思路
-
问题分析:
- 序列γ是通过将β反转、旋转后与α进行卷积生成的。
- 解密需要从γ和β中恢复α,这可以通过FFT实现高效的卷积和逆卷积运算。
-
关键步骤:
- 对序列β和γ进行FFT变换。
- 在频域中求解α的FFT变换。
- 对结果进行逆FFT变换得到时域的α序列。
-
算法选择:
- 使用FFT加速卷积运算。
- 利用复数运算处理实数序列的变换。
- 通过数学推导建立β、γ和α之间的关系式。
分析
-
FFT变换:
- 将β和γ转换到频域,便于进行卷积运算。
- 频域中的乘法对应时域中的卷积。
-
频域求解:
- 在频域中,α的FFT可以通过γ的FFT除以β的FFT得到。
- 需要考虑零点和数值稳定性。
-
逆FFT变换:
- 将频域结果转换回时域,得到序列α。
- 对结果进行四舍五入,保留四位小数。
实现步骤
-
输入处理:
- 读取序列长度n。
- 读取序列β和γ的数值。
-
FFT变换:
- 对β和γ进行FFT变换。
- 初始化FFT所需的参数和临时数组。
-
频域运算:
- 在频域中计算α的FFT。
- 处理复数除法和数值稳定性。
-
逆FFT变换:
- 对结果进行逆FFT变换。
- 调整结果并四舍五入。
-
输出结果:
- 输出恢复的序列α,保留四位小数。
代码解释
- 复数运算:定义了复数的加减乘除运算,支持FFT所需的操作。
- FFT实现:包括FFT和逆FFT的实现,以及初始化函数。
- Bluestein算法:用于处理非2的幂次长度的FFT。
- 主函数:读取输入,调用FFT和逆FFT,输出结果。
该方法通过FFT高效地解决了卷积和逆卷积问题,确保在合理时间内恢复原始序列α。
代码
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long #define re register #define cs const cs double PI=acos(-1); struct Complex{ double x,y; Complex(){} Complex(cs double &_x,cs double &_y):x(_x),y(_y){} Complex conj()cs{return Complex(x,-y);} friend Complex operator+(cs Complex &a,cs Complex &b){return Complex(a.x+b.x,a.y+b.y);} friend Complex operator-(cs Complex &a,cs Complex &b){return Complex(a.x-b.x,a.y-b.y);} friend Complex operator*(cs Complex &a,cs Complex &b){return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);} friend Complex operator/(cs Complex &a,cs double &b){return Complex(a.x/b,a.y/b);} friend Complex operator/(cs Complex &a,cs Complex &b){return a*b.conj()/(b.x*b.x+b.y*b.y);} }; cs int N=1<<17|1; int r[N<<2|1]; Complex w[N<<2|1]; inline void FFT(Complex *A,int len,int typ){ if(typ==-1)std::reverse(A+1,A+len); for(int re i=0;i<len;++i)if(i<r[i])std::swap(A[i],A[r[i]]); for(int re i=1;i<len;i<<=1) for(int re j=0;j<len;j+=i<<1) for(int re k=0;k<i;++k){ static Complex x,y; x=A[j+k],y=A[j+k+i]*w[len/i/2*k]; A[j+k]=x+y; A[j+k+i]=x-y; } if(typ==-1)for(int re i=0;i<len;++i)A[i]=A[i]/len; } inline void init_rev(int len){ static int last;if(last==len)return ;last=len; for(int re i=0;i<len;++i) r[i]=r[i>>1]>>1|((i&1)*(len>>1)), w[i]=Complex(cos(2*PI*i/len),sin(2*PI*i/len)); } inline void BS(Complex *a,int l,int typ){ static Complex A[N<<2|1],B[N<<2|1]; int l2=l<<1; for(int re i=0;i<l;++i)A[i]=a[i]*Complex(cos(PI*i*i/l),typ*sin(PI*i*i/l)); for(int re i=0;i<l2;++i)B[i]=Complex(cos(PI*(i-l)*(i-l)/l),-typ*sin(PI*(i-l)*(i-l)/l)); int len=1;while(len<l*3)len<<=1; for(int re i=l;i<len;++i)A[i]=Complex(0,0); for(int re i=l2;i<len;++i)B[i]=Complex(0,0); init_rev(len); FFT(A,len,1),FFT(B,len,1); for(int re i=0;i<len;++i)A[i]=A[i]*B[i]; FFT(A,len,-1); for(int re i=0;i<l;++i)a[i]=A[i+l]*Complex(cos(PI*i*i/l),typ*sin(PI*i*i/l)); if(typ==-1)for(int re i=0;i<l;++i)a[i]=a[i]/l; } int n; Complex a[N],b[N],c[N]; signed main(){ scanf("%d",&n); for(int re i=0;i<n;++i)scanf("%lf",&b[i].x); for(int re i=0;i<n;++i)scanf("%lf",&c[i].x); BS(b,n,1),BS(c,n,1); for(int re i=0;i<n;++i)a[i]=c[i]/b[i]; BS(a,n,-1); for(int re i=0;i<n;++i)printf("%.4f\n",a[i].x); return 0; }
- 1
信息
- ID
- 1822
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者