思路比较直观。设A(x)=Σxai。先把只选一种的统计进去。然后考虑选两种,这个直接A(x)自己卷起来就好了,要去掉选同一种的情况然后除以2。现在得到了选两种的每种权值的方案数,再把这个卷上A(x)。得到这个后考虑去重,其中重复的就是选了两个相同的和另外一个,那么再把选两个相同的生成函数搞出来卷上A,减掉选三个相同的。把这个东西减掉之后再除以3。说了半天也不知道在说啥,总之是容斥原理很基础的应用。

  有些卡精度,用long double才过,可能是我写丑了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 270000
#define double long double
const double PI=3.14159265358979324;
struct complex
{
double x,y;
complex operator +(const complex&a) const
{
return (complex){x+a.x,y+a.y};
}
complex operator -(const complex&a) const
{
return (complex){x-a.x,y-a.y};
}
complex operator *(const complex&a) const
{
return (complex){x*a.x-y*a.y,x*a.y+y*a.x};
}
}w[N],v[N],u[N];
int n,m,t,a[N],r[N];
long long f[N];
void DFT(int n,complex *a,int p)
{
for (int i=;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
for (int i=;i<=n;i<<=)
{
complex wn=(complex){cos(*PI/i),p*sin(*PI/i)};
for (int j=;j<n;j+=i)
{
complex w=(complex){,};
for (int k=j;k<j+(i>>);k++,w=w*wn)
{
complex x=a[k],y=w*a[k+(i>>)];
a[k]=x+y,a[k+(i>>)]=x-y;
}
}
}
}
void mul(int n,complex *a,complex *b)
{
for (int i=;i<n;i++) r[i]=(r[i>>]>>)|(i&)*(n>>);
for (int i=;i<n;i++) a[i].y=a[i].x-b[i].x,a[i].x=a[i].x+b[i].x;
DFT(n,a,);
for (int i=;i<n;i++) a[i]=a[i]*a[i];
DFT(n,a,-);
for (int i=;i<n;i++) a[i].x=a[i].x/n/;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj3771.in","r",stdin);
freopen("bzoj3771.out","w",stdout);
const char LL[]="%d %I64d\n";
#else
const char LL[]="%d %lld\n";
#endif
n=read();
for (int i=;i<=n;i++)
{
int x=read();
m=max(m,x);
w[x].x=v[x].x=f[x]=a[x]=;
}
t=;while (t<=(m<<)) t<<=;
mul(t,w,v);
for (int i=;i<=m;i++) if (a[i]) w[i<<].x--;
for (int i=;i<=m*;i++) f[i]+=w[i].x=(int)(w[i].x/+0.5);
for (int i=m*+;i<t;i++) w[i].x=w[i].y=;
for (int i=;i<=m;i++) v[i].x=a[i],v[i].y=;
for (int i=m+;i<t;i++) v[i].x=v[i].y=;
t=;while (t<=m*) t<<=;
mul(t,w,v);
for (int i=;i<t;i++) u[i].x=(i&)?:a[i>>];
for (int i=;i<=m;i++) v[i].x=a[i],v[i].y=;
for (int i=m+;i<t;i++) v[i].x=,v[i].y=;
mul(t,u,v);
for (int i=;i<=m;i++) if (a[i]) u[i*].x--;
for (int i=;i<=m*;i++) f[i]+=(long long)((w[i].x-u[i].x)/+0.5);
for (int i=;i<=m*;i++)
if (f[i]) printf(LL,i,f[i]);
return ;
}

BZOJ3771 Triple(FFT+容斥原理)的更多相关文章

  1. 【bzoj3771】Triple FFT+容斥原理

    题目描述 樵夫的每一把斧头都有一个价值,不同斧头的价值不同.总损失就是丢掉的斧头价值和. 他想对于每个可能的总损失,计算有几种可能的方案. 注意:如果水神拿走了两把斧头a和b,(a,b)和(b,a)视 ...

  2. [BZOJ 3771] Triple(FFT+容斥原理+生成函数)

    [BZOJ 3771] Triple(FFT+生成函数) 题面 给出 n个物品,价值为别为\(w_i\)且各不相同,现在可以取1个.2个或3个,问每种价值和有几种情况? 分析 这种计数问题容易想到生成 ...

  3. BZOJ 3771 Triple FFT+容斥原理

    解析: 这东西其实就是指数型母函数? 所以刚开始读入的值我们都把它前面的系数置为1. 然后其实就是个多项式乘法了. 最大范围显然是读入的值中的最大值乘三,对于本题的话是12W? 用FFT优化的话,达到 ...

  4. 【BZOJ3771】Triple 生成函数 FFT 容斥原理

    题目大意 有\(n\)把斧头,不同斧头的价值都不同且都是\([0,m]\)的整数.你可以选\(1\)~\(3\)把斧头,总价值为这三把斧头的价值之和.请你对于每种可能的总价值,求出有多少种选择方案. ...

  5. 2018.12.31 bzoj3771: Triple(生成函数+fft+容斥原理)

    传送门 生成函数经典题. 题意简述:给出nnn个数,可以从中选1/2/31/2/31/2/3个,问所有可能的和对应的方案数. 思路: 令A(x),B(x),C(x)A(x),B(x),C(x)A(x) ...

  6. SPOJ Triple Sums(FFT+容斥原理)

    # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream& ...

  7. bzoj3771: Triple(容斥+生成函数+FFT)

    传送门 咳咳忘了容斥了-- 设\(A(x)\)为斧头的生成函数,其中第\(x^i\)项的系数为价值为\(i\)的斧头个数,那么\(A(x)+A^2(x)+A^3(x)\)就是答案(于是信心满满的打了一 ...

  8. bzoj 3771: Triple【生成函数+FFT+容斥原理】

    瞎搞居然1A,真是吃鲸 n的范围只有聪明人能看见--建议读题3遍 首先看计数就想到生成函数,列出多项式A(x),然后分别考虑123 对于选一个的直接计数即可: 对于选两个的,\( A(x)^2 \), ...

  9. 【BZOJ 3771】 3771: Triple (FFT+容斥)

    3771: Triple Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 547  Solved: 307 Description 我们讲一个悲伤的故事. ...

随机推荐

  1. Kafka笔记--常用指令(新建、删除topic)

    新建topic ./kafka-topics.sh --zookeeper 192.168.1.160:2181 --create --topic kafkatestsmall2 --partitio ...

  2. sprintf()函数用法

    sprintf()用法见操作手册:http://www.php.net/sprintf 简单写下format的用法: 1. + - 符号,数字 2. 填充字符 默认是空格,可以是0.如果其他字符填充, ...

  3. Java使用数字证书加密通信(加解密/加签验签)

    本文中使用的Base64Utils.java可参考:http://www.cnblogs.com/shindo/p/6346618.html 证书制作方法可参考:http://www.cnblogs. ...

  4. git 用法---成功添加一个文件到github

    一.git 提交 全部文件 git add . git add xx命令可以将xx文件添加到暂存区,如果有很多改动可以通过 git add -A .来一次添加所有改变的文件.注意 -A 选项后面还有一 ...

  5. 【LeetCode225】 Implement Stack using Queues★

    1.题目 2.思路 3.java代码 import java.util.LinkedList; import java.util.Queue; public class MyStack { priva ...

  6. 验证码处理类:UnCodebase.cs + BauDuAi 读取验证码的值(并非好的解决方案)

    主要功能:变灰,去噪,等提高清晰度等 代码类博客,无需多说,如下: public class UnCodebase { public Bitmap bmpobj; public UnCodebase( ...

  7. easyui datagrid remoteSort的实现 Controllers编写动态的Lambda表达式 IQueryable OrderBy扩展

    EF 结合easy-ui datagrid 实现页面端排序 EF动态编写排序Lambda表达式 1.前端页面 var mainListHeight = $(window).height() - 20; ...

  8. C. Banh-mi

    链接 [http://codeforces.com/contest/1062/problem/C] 题意 给你有n个字符(0 or 1)的串,当去某个位置时所有的剩下的位置都加上这个位置的数字,q次查 ...

  9. C. Meme Problem

    链接 [http://codeforces.com/contest/1076/problem/C] 题意 a+b=d and a⋅b=d. 计算出a和b 分析 ab=a(d-a)=d aa-ad+d= ...

  10. 2016.3.24 OneZero站立会议

    会议时间:2016.3.24 15:35-15:55 会议成员:王巍 夏一名 冉华 张敏 会议内容: 1.确立UI界面原形(见http://www.cnblogs.com/zhangminss/p/5 ...