Anarchy的解题报告

5 篇文章 0 订阅
1 篇文章 0 订阅

题目大意:
假设高斯定理在 m 维空间成立
已知m维空间所有整点电荷 aj
给出 m 维空间下x,y两点距离公式
这里写图片描述
以及x点在y点引发的电势公式
这里写图片描述

这里写图片描述
降序输出求前100个点的电势

T51m18n3105
时限 7s

考试的时候看这道题的时候 感觉这道题根本不可做啊???
部分分很友好啊?除了一个5分的点 其他我都不会。。

看完题解之后整个人都不好了。。
然后我用了一个下午来调试 压常

其实 上面那个式子就是卷积的形式 只不过 这个是m维卷积。。。(做毛线啊
好吧 m维卷积大家都会喜闻乐见的 FWT ?
平常的FWT一般都是每一维大小为2 的情况 当大于2的时候我们可以直接上DFT
然后我们会发现这个循环卷积也不好处理
怎么办呢?

将DFT的式子拆成卷积形式 然后FFT优化卷积之后即可得出
BluesteinsAlgorithm
时间复杂度 O(nlog2n)
注意常数很大 所以不得不不预处理单位根 以及一些黑科技

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
#define ld double
ld Sin[20],Cos[20];
struct com
{
    ld a,b;
    com(){}
    com(ld a,ld b):a(a),b(b){}
    friend com operator +(com a,com b){return com(a.a+b.a,a.b+b.b);}
    friend com operator -(com a,com b){return com(a.a-b.a,a.b-b.b);}
    friend com operator *(com a,com b){return com(a.a*b.a-a.b*b.b,a.b*b.a+a.a*b.b);}
    friend com operator /(com a,ld b){return com(a.a/b,a.b/b);}
    friend com operator *(com a,ld b){return com(a.a*b,a.b*b);}

};
const
    ld pi=acos(-1);
int rev[2200005];
void FFT(com *a,int n,int fl)
{
    int Len=1<<n;
    for(int i=0;i<Len;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<n-1);
    for(int i=0;i<Len;i++)if(rev[i]>i)swap(a[rev[i]],a[i]);
    for(int p=0,i=1;i<Len;i*=2,p++)
    {
        com w=com(Cos[p],fl*Sin[p]);
        for(int j=0;j<Len;j+=2*i)
        {
            com w0=com(1,0);
            for(int k=0;k<i;k++)
            {
                com x=a[j+k],y=w0*a[i+j+k];
                a[j+k]=x+y;
                a[j+k+i]=x-y;
                w0=w0*w;
            }
        }
    }
    if(fl==-1)
        for(int i=0;i<Len;i++)a[i]=a[i]/Len;
}

com c[2200005],b[2200005];
int C;
ld SIN[2200005],COS[2200005];
void DFT(com* a,int d,int n,int fl)
{
    int N=1;
    for(;(1<<N)<(3*n);N++);
    int P=C/2/n,Nf=2*n;
    for(int i=0;i<2*n;i++)
        b[i]=com(COS[i*1ll*i%Nf*P],fl*SIN[i*1ll*i%Nf*P]);       
    for(int i=0;i<n;i++)
        c[n-i]=com(COS[i*1ll*i%Nf*P],-fl*SIN[i*1ll*i%Nf*P])*a[i*d];
    if(n<=50)
    {
        for(int i=n;i<2*n;i++)
        {
            int pos=i-n;
            pos*=d;
            a[pos]=com(0,0);
            for(int j=0;j<=i;j++)
            a[pos]=a[pos]+b[i-j]*c[j];
        }
    }
    else
    {
        for(int i=0;i<N;i++)
            Cos[i]=cos(pi/(1<<i)),Sin[i]=sin(pi/(1<<i));
        FFT(b,N,1);
        FFT(c,N,1);
        for(int i=0;i<(1<<N);i++)b[i]=b[i]*c[i];
        FFT(b,N,-1);
        for(int i=0;i<n;i++)a[i*d]=b[i+n];
    }
    for(int i=0;i<n;i++)
            a[i*d]=a[i*d]*com(COS[i*1ll*i%Nf*P],-fl*SIN[i*1ll*i%Nf*P]);
    if(fl==-1)
        for(int i=0;i<n;i++)a[i*d]=a[i*d]/n;
    for(int i=0;i<(1<<N);i++)b[i]=c[i]=com(0,0);
}
int s[2200005];
void FWT(com* a,int n,int m,int fl)
{
    int len=1;
    for(int i=0;i<m;len*=s[i++])
        for(int j=0;j<n;j+=len*s[i])
            for(int k=0;k<len;k++)
                DFT(a+j+k,len,s[i],fl);
}
com Da[2200005];
int no[2200005];
bool cmp(int a,int b)
{
    return Da[a].a>Da[b].a;
}
int main()
{
    freopen("anarchy.in","r",stdin);
    freopen("anarchy.out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int m,n=1;
        scanf("%d",&m);
        for(int i=0;i<m;i++)scanf("%d",s+i),n*=s[i];C=n;
        for(int i=0;i<n;i++)
        {
            int t;
            scanf("%d",&t);
            Da[i].a=t;
            Da[i].b=1;
            for(int t=i,j=0;j<m;t/=s[j++])
                Da[i].b*=t%s[j]+1;
            Da[i].b=powl(Da[i].b,2.0/m); 
            Da[i].b/=2.*m;
            Da[i]=com(Da[i].a+Da[i].b,Da[i].a-Da[i].b); 
        }
        C*=2;
        for(int i=0;i<2*n;i++)
            SIN[i]=sin(2*pi/2/n*i),COS[i]=cos(2*i*pi/2/n);
        FWT(Da,n,m,1);
        for(int i=0;i<n;i++)Da[i]=Da[i]*Da[i];
        FWT(Da,n,m,-1);

        for(int i=0;i<n;i++)no[i]=i;
        sort(no,no+n,cmp);
        for(int i=0;i<min(n,100);i++)
            printf("%.9f ",Da[no[i]].a/4);
        puts("");

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值