zoukankan      html  css  js  c++  java
  • BZOJ 3771 Triple (FFT+生成函数+容斥)

    题面传送门

    题目大意:给你互不相同的$n$个数,在其中任选$1$~$3$个数,不能重复选数,设它们的和为$S$。对于所有可能的$S$,求选出的数和为$S$方案总数,选数没有顺序。

    先对所有的数弄一个生成函数$A$,有数的位置权值为$1$

    如果我们要选$x$个数,求方案数。只需要对$A$求$x$次卷积。

    然而题目要求选数是无序的,且不能重复选数

    选$1$个数的方案就是$A$

    选$2$个数时,需要去掉重复选同一个数的情况,即$(A*A-B)/2$,$B$是相同的数选$2$次时的生成函数

    选$3$个数的情况更复杂

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

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

    然而情况二还可能把情况一去掉,需要再加回来

    最终答案就是$A+(A*A-B)/2+(A*A*A-3*B*A+2*C)/6$

     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
    ",i,s1[i]+s2[i]+s3[i]);
    84      
    85     return 0;
    86 }
  • 相关阅读:
    Wwise音频解决方案概述
    图形学中的几何光学理论与视觉现象
    Visual Studio 2015 Tools for Unity使用基础
    C++编译器优化技术:RVO、NRVO和复制省略
    【ElasticSearch】 ElasticSearch基本概念和RESTful API(四)
    【ElasticStack】入门介绍(三)
    【Java】开发一个Java-SDK
    【Java】Maven 打包可运行jar包
    【SpringBoot】Spring Boot Admin 微服务应用监控
    【Java面试题】方法的参数传递机制
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10345095.html
Copyright © 2011-2022 走看看