# BZOJ 3771 Triple (FFT+生成函数+容斥)

1.首先要去掉重复选$3$次同一个数的情况，设相同的数选$3$次时的生成函数为$C$

2.还要去掉 选$2$次相同的数，再选另一个数的情况，这种情况的生成函数是$3*B*A$

1 #include <cmath>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #define N1 (1<<18)+10
6 #define ll long long
7 #define dd double
8 using namespace std;
9
10
11 int gint()
12 {
13     int ret=0,fh=1; char c=getchar();
14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
16     return ret*fh;
17 }
18
19 int r[N1];
20 const dd pi=acos(-1);
21 struct cp{
22 dd x,y;
23 friend cp operator + (const cp &s1,const cp &s2){ return (cp){s1.x+s2.x,s1.y+s2.y}; }
24 friend cp operator - (const cp &s1,const cp &s2){ return (cp){s1.x-s2.x,s1.y-s2.y}; }
25 friend cp operator * (const cp &s1,const cp &s2){ return (cp){s1.x*s2.x-s1.y*s2.y,s1.y*s2.x+s1.x*s2.y}; }
26 }a[N1],b[N1],c[N1],f[N1];
27
28 void init()
29 {
30     memset(a,0,sizeof(a));
31     memset(b,0,sizeof(b));
32     memset(c,0,sizeof(c));
33 }
34
35 void FFT(cp *s,int len,int type)
36 {
37     int i,j,k; cp wn,w,t;
38     for(i=0;i<len;i++) if(i<r[i]) swap(s[i],s[r[i]]);
39     for(k=2;k<=len;k<<=1)
40     {
41         wn=(cp){cos(2.0*pi*type/k),sin(2.0*pi*type/k)};
42         for(i=0;i<len;i+=k)
43         {
44             w=(cp){1,0};
45             for(j=0;j<(k>>1);j++,w=w*wn)
46             {
47                 t=w*s[i+j+(k>>1)];
48                 s[i+j+(k>>1)]=s[i+j]-t;
49                 s[i+j]=s[i+j]+t;
50             }
51         }
52     }
53 }
54 int n,ma,len,L;
55 int v[N1],s1[N1],s2[N1],s3[N1],ans[N1];
56
57 int main()
58 {
59     scanf("%d",&n); int i;
60     for(i=1;i<=n;i++) v[i]=gint(),ma=max(ma,v[i]),s1[v[i]]++; // 1 -> A
61
62     for(len=1,L=0;len<3*ma;len<<=1,L++);
63     for(i=1;i<=n;i++) a[v[i]].x=1,b[v[i]<<1].x=1;//c[v[i]*3].x=1;
64     for(i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
65     FFT(a,len,1); FFT(b,len,1);// FFT(c,len,1);
66
67     for(i=0;i<len;i++) f[i]=a[i]*a[i]; // 2 -> (A*A-B)/2
68     FFT(f,len,-1);
69     for(i=1;i<=n;i++) s2[v[i]<<1]--;
70     for(i=0;i<len;i++) s2[i]=(int)(f[i].x/len+0.1);
71     for(i=0;i<len;i++) s2[i]/=2;
72
73     for(i=0;i<len;i++) f[i]=a[i]*a[i]*a[i]; // 3 -> (A*A*A-3*B*A+2*C)/6
74     FFT(f,len,-1);
75     for(i=0;i<len;i++) s3[i]+=(int)(f[i].x/len+0.1);
76     for(i=0;i<len;i++) f[i]=a[i]*b[i];
77     FFT(f,len,-1);
78     for(i=0;i<len;i++) s3[i]-=( (int)(f[i].x/len+0.1) )*3;
79     for(i=1;i<=n;i++) s3[v[i]*3]+=2;
80     for(i=0;i<len;i++) s3[i]/=6;
81
82     for(i=1;i<=len;i++) if(s1[i]+s2[i]+s3[i]>0)
83         printf("%d %d\n",i,s1[i]+s2[i]+s3[i]);
84
85     return 0;
86 }

posted @ 2019-02-01 11:00  guapisolo  阅读(113)  评论(0编辑  收藏  举报