gym100783 C.Golf Bot

链接

https://codeforces.com/gym/100783

题解

构造向量 a a a,如果某个距离存在,就把那个位置设置为 1 1 1,否则设置为 0 0 0
然后多项式卷积

代码

#include <bits/stdc++.h>
#define maxn 600000
#define eps 1e-8
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
struct comp
{
    double x, y;
    comp(double x, double y):x(x),y(y){}
    comp():x(0),y(0){}
    comp operator+(comp t){return comp(x+t.x, y+t.y);}
    comp operator-(comp t){return comp(x-t.x, y-t.y);}
    comp operator*(comp t){return comp(x*t.x-y*t.y, x*t.y+t.x*y);}
};
struct FFT
{
    int up, R[maxn];
    const double pi=acos(-1);
    void init(int bound)    //bound是积多项式的最高次幂
    {
        int L(0);
        for(up=1;up<=bound;up<<=1,L++);
        for(int i=0;i<up;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
    }
    void fft(comp* a, int opt)
    {
        int i, j, k;
        comp wn, w, x, y;
        for(i=0;i<up;i++)if(i>R[i])swap(a[i],a[R[i]]);
        for(i=1;i<up;i<<=1)
        {
            wn=comp(cos(pi/i),opt*sin(pi/i));
            for(j=0;j<up;j+=i<<1)
                for(w=comp(1,0),k=0;k<i;k++,w=w*wn)
                {
                    x=a[k+j], y=a[k+j+i]*w;
                    a[k+j]=x+y, a[k+j+i]=x-y;
                }
        }
        if(opt==-1)for(i=0;i<up;i++)a[i].x/=up;
    }
    void juan(comp* a, comp* b, comp* c)
    {
        fft(a,1), fft(b,1);
        for(int i=0;i<up;i++)c[i]=a[i]*b[i];
        fft(c,-1);
    }
}fft;
int read(int x=0)
{
    int c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return f*x;
}
comp a[maxn], b[maxn], c[maxn];
int main()
{
    int n, m, i, ans, mx;
    while(~scanf("%d",&n))
    {
        mx=0;
        for(i=0;i<maxn;i++)a[i]=b[i]=c[i]=comp();
        for(i=0;i<n;i++)
        {
            auto t=read();
            b[t].x=a[t].x=1;
        }
        fft.init(400000);
        fft.juan(a,b,c);
        fft.fft(a,-1);
        for(i=0;i<maxn;i++)c[i]=c[i]+a[i];
        m=read();
        ans=0;
        while(m--)
        {
            auto q=read();
            if(fabs(c[q].x)>1e-2)ans++;//printf("%.5lf %.5lf\n",c[q].x,c[q].y);
        }
        printf("%d\n",ans);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值