题解
设 表示原序列中值为 的元素的个数
构造三个多项式
其中
先算一把斧头的,就是
然后算两把斧头的,
然后算三把的,
代码
#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 300000
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
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;
}
struct FFT
{
int n, R[maxn];
typedef complex<double> C;
C a[maxn], b[maxn], w[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]=C(0,0);
}
void fft(C* a, int opt)
{
int i, j, k, d;
for(i=0;i<n;i++)if(i>R[i])swap(a[i],a[R[i]]);
for(i=0;i<n;i++)w[i]=C(cos(pi*i/n),opt*sin(pi*i/n));
for(d=0,k=__builtin_ctz(n);(1<<d)<n;d++)
{
int m=1<<d, m2=m<<1;
for(i=0;i<n;i+=m2)for(j=0;j<m;j++)
{
C &x=a[i+j+m], &y=a[i+j], t=w[j<<(k-d)]*x;
x=y-t, y=y+t;
}
}
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;
FFT::C F[maxn], G[maxn], H[maxn], A[maxn];
ll ans[maxn], n;
int main()
{
ll i;
n=read();
fft.init(3*40000);
rep(i,1,n)
{
auto one = FFT::C(1,0);
ll x=read();
F[x]+=one;
G[2*x]+=one;
H[3*x]+=one;
}
fft.fft(F,1);
fft.fft(G,1);
fft.fft(H,1);
rep(i,0,fft.n-1)
{
A[i] += F[i];
A[i] += FFT::C(1.0/2) * ( F[i]*F[i] - G[i] );
A[i] += FFT::C(1.0/6) * ( F[i]*F[i]*F[i] - FFT::C(3)*(F[i]*G[i]-H[i]) - F[i] );
}
fft.fft(A,-1);
rep(i,0,fft.n-1)ans[i]=ll((A[i]+FFT::C(0.5)).real());
rep(i,0,fft.n-1)if(ans[i])printf("%lld %lld\n",i,ans[i]);
return 0;
}