# BZOJ3771

### 题解

1，取1个物品
A n s = A ( x ) Ans=A(x)
2，取2个物品
A n s = A ( x ) 2 − B ( x ) 2 Ans=\frac{A(x)^2-B(x)}{2}
3，取3个物品
A n s = A ( x ) 3 − 3 A ( x ) B ( x ) + 2 C ( x ) 6 Ans=\frac{A(x)^3-3A(x)B(x)+2C(x)}{6}

### 代码

#include  <cmath>
#include  <cstdio>
#include  <climits>
#include  <cstring>
#include  <cstdlib>
#include  <iostream>
#include  <algorithm>
using namespace std;
const int M=4e5+9;
const double pi=acos(-1.0);
int n,m,r[M],l,lim=1;
struct complex{
double x,y;
complex(double xx=0,double yy=0){x=xx,y=yy;}
friend inline complex operator+(complex a,complex b){return complex(a.x+b.x,a.y+b.y);}
friend inline complex operator-(complex a,complex b){return complex(a.x-b.x,a.y-b.y);}
friend inline complex operator*(complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
friend inline complex operator/(complex a,double b){return complex(a.x/b,a.y/b);}
friend inline complex operator*(complex a,double b){return complex(a.x*b,a.y*b);}
}a[M],b[M],c[M],ans[M];
void FFT(complex *A,int type){
for(int i=0;i<lim;i++) if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=1;mid<lim;mid<<=1){
complex W(cos(pi/mid),type*sin(pi/mid));
for(int R=mid<<1,j=0;j<lim;j+=R){
complex w(1,0);
for(int k=0;k<mid;k++,w=w*W){
complex x=A[j+k],y=w*A[j+k+mid];
A[j+k]=x+y;
A[j+mid+k]=x-y;
}
}
}if(type==-1) for(int i=0;i<lim;i++) A[i]=A[i]/lim;
}
signed main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x;scanf("%d",&x);
a[x].x++,b[x*2].x++,c[x*3].x++;
m=max(m,x*3);
}
while(lim<m*2) lim<<=1,l++;
for(int i=0;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
FFT(a,1),FFT(b,1),FFT(c,1);
for(int i=0;i<=lim;i++) ans[i]=(a[i]*a[i]*a[i]-3.0*a[i]*b[i]+2.0*c[i])/6.0+(a[i]*a[i]-b[i])/2.0+a[i];
FFT(ans,-1);
for(int i=0;i<=m;i++)
if((int)(ans[i].x+0.5)) printf("%d %d\n",i,(int)(ans[i].x+0.5));
return 0;
}


02-21 476
02-28 368
09-02 786
04-25 742
05-26 1214
08-11 7951
03-26 147