2019上海站网络预选赛 C.Triple

链接

点击跳转

题解

FFT

代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef complex<double> C;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
ll a[maxn], b[maxn], c[maxn], sa[maxn], sb[maxn], s[maxn], n=100000, N;
struct FFT
{
    int n, R[maxn];
    typedef complex<double> C;
    C a[maxn], b[maxn];
    const double pi=acos(-1);
    void init(int bound)    //bound是积多项式的最高次幂
    {
        int L(0);
        for(n=1;n<=bound;n<<=1,L++);
        for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1)),a[i]=b[i]=0;
    }
    void fft(C* a, int opt)
    {
        int i, j, k;
        C wn, w, x, y;
        for(i=0;i<n;i++)if(i>R[i])swap(a[i],a[R[i]]);
        for(i=1;i<n;i<<=1)
        {
            wn=C(cos(pi/i),opt*sin(pi/i));
            for(j=0;j<n;j+=i<<1)
                for(w=C(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<n;i++)a[i]/=n;
    }
    void run()
    {
        fft(a,1), fft(b,1);
        for(int i=0;i<n;i++)a[i]*=b[i];
        fft(a,-1);
    }
}fft;
ll abc(ll* a, ll *b, ll *c)
{
    ll i, ans=0, s1=0, s2=0;
    fft.init(2*n);
    rep(i,n)fft.a[i]=C(a[i]);
    rep(i,n)fft.b[i]=C(b[i]);
    fft.run();
    for(i=n;i;i--)sa[i]=sa[i+1]+a[i];
    for(i=n;i;i--)sb[i]=sb[i+1]+b[i];
    for(i=2*n;i;i--)s[i]=s[i+1]+ll(fft.a[i].real()+0.5);
    rep(i,n)
    {
        ll t=s[i];
        t -= sa[i]*sb[1];
        t -= sb[i]*sa[1];
        t += sa[i]*sb[i];
        ans += c[i]*t;
    }
    return ans;
}
ll abb(ll *a, ll *b, ll *c)
{
    ll i, j, ans=0;
    rep(i,n)sa[i]=sa[i-1]+a[i];
    rep(i,n)ans+=b[i]*c[i]*sa[i-1];
    return ans;
}
ll aaa(ll *a, ll *b, ll *c)
{
    ll i, ans=0;
    rep(i,n)ans+=a[i]*b[i]*c[i];
    return ans;
}
int main()
{
    ll i, j, k, T=read(), ans=0, kase=0;
    while(T--)
    {
        N=read();
        rep(i,n)a[i]=b[i]=c[i]=0;

        ans=0;

        if(N<=1000)
        {
            rep(i,N)a[i]=read();
            rep(i,N)b[i]=read();
            rep(i,N)c[read()]++;
            rep(i,n)s[i]=s[i-1]+c[i];

            for(i=1;i<=N;i++)
            {
				for(j=1;j<=N;j++)
                {
					ll smx=a[i]+b[j], smn=max(1ll,abs(a[i]-b[j]));
					ans += s[min(n,smx)]-s[smn-1];
                }
            }
        }
        else
        {
            rep(i,N)a[read()]++;
            rep(i,N)b[read()]++;
            rep(i,N)c[read()]++;
            
            ans=0;
            ans+=abc(a,b,c);
            ans+=abc(a,c,b);
            ans+=abc(b,c,a);

            ans+=abb(a,b,c);
            ans+=abb(b,a,c);
            ans+=abb(c,a,b);

            ans+=aaa(a,b,c);
        }

        printf("Case #%lld: %lld\n",++kase,ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值