题解:P17217 [ICPC 2017 Nanning R] Five Dimensional Discrete Fourier Transform
lailai0916 · · 题解
题意简述
给定带异或系数与相位因子的五维复数组。求其离散傅里叶变换中,所有频域元素实部绝对值的归一化总和。
解题思路
直接计算五维离散傅里叶变换(Discrete Fourier Transform,DFT)需要枚举两组五维下标。关键是把异或值拆成常数项和
定义第
异或结果的第
右侧共有一个常数项和
令
再令
每个一维变换的长度至多为
所有下标都是整数,long double 约化
设
参考代码
#include <bits/stdc++.h>
using namespace std;
using ld=long double;
using cd=complex<double>;
const int K=5;
const int N=15;
const int L=105;
const int R=1005;
const ld lpi=acosl(-1);
const double pi=acos(-1);
const double cf[K]={7.5,-0.5,-1,-2,-4};
const int sgn[K]={1,-1,1,-1,1};
cd f[K][K][N],lf[L][K],rf[R][K];
void calc(int d,int n,double a)
{
for(int i=0;i<K;i++)
{
for(int j=0;j<n;j++)
{
f[d][i][j]=0;
for(int k=0;k<n;k++)
{
double w=i&&((k>>(i-1))&1)?-1:1,x=(sgn[d]*a-2*pi*j/n)*k;
f[d][i][j]+=w*cd(cos(x),sin(x));
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin>>T;
cout<<fixed<<setprecision(6);
while(T--)
{
int n[K];
for(int i=0;i<K;i++)cin>>n[i];
ld a;
cin>>a;
double ang=remainderl(a,2*lpi);
for(int i=0;i<K;i++)calc(i,n[i],ang);
int lc=n[0]*n[1];
for(int i=0;i<lc;i++)
{
int x=i/n[1],y=i%n[1];
for(int j=0;j<K;j++)lf[i][j]=cf[j]*f[0][j][x]*f[1][j][y];
}
int rc=n[2]*n[3]*n[4];
for(int i=0;i<rc;i++)
{
int x=i/(n[3]*n[4]),y=i/n[4]%n[3],z=i%n[4];
for(int j=0;j<K;j++)rf[i][j]=f[2][j][x]*f[3][j][y]*f[4][j][z];
}
double ans=0;
for(int i=0;i<lc;i++)
{
for(int j=0;j<rc;j++)
{
cd cur=0;
for(int k=0;k<K;k++)cur+=lf[i][k]*rf[j][k];
ans+=abs(cur.real());
}
}
int siz=1;
for(int i=0;i<K;i++)siz*=n[i];
cout<<ans/(siz*sqrt(1.0*siz))<<'\n';
}
return 0;
}