题目描述

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

输入

第一行是整数N,表示有N把斧头。
接下来n行升序输入N个数字Ai,表示每把斧头的价值。

输出

若干行,按升序对于所有可能的总损失输出一行x y,x为损失值,y为方案数。

样例输入

4
4
5
6
7

样例输出

4 1
5 1
6 1
7 1
9 1
10 1
11 2
12 1
13 1
15 1
16 1
17 1
18 1


题解

FFT+容斥原理

一个数的方案数$f(x)$,就是原序列的生成函数(初学时理解为桶 = =)。

两个数的方案数为$(f*f)(x)$,但其中包含了两次使用了同一个数的方案数$g(x)=f(2x)$,而其余的方案统计了两次,所以方案数为$\frac 12(f*f-g)(x)$。

三个数的方案数为$(f*f*f)(x)$,但其中包含了三次使用了同一个数的方案数$h(x)=f(3x)$,包含了使用了两次同一个数,另一个数不同的方案数$(f*g-h)(x)*3$(里面减掉$h$是因为三次使用同一个数的方案数被重复计算,而乘3是因为在$(f*f*f)(x)$中计算了3次),而其余的方案统计了,所以方案数为$\frac 16((f*f*f-3*f*g+2*h)(x))$。

最后数值不为0的就是答案。

#include <cstdio>
#include <cmath>
#include <algorithm>
#define N 1 << 19
#define pi acos(-1)
using namespace std;
typedef long long ll;
struct data
{
double x , y;
data() {x = y = 0;}
data(double x0 , double y0) {x = x0 , y = y0;}
data operator+(const data a)const {return data(x + a.x , y + a.y);}
data operator-(const data a)const {return data(x - a.x , y - a.y);}
data operator*(const data a)const {return data(x * a.x - y * a.y , x * a.y + y * a.x);}
}a[N] , b[N] , c[N] , d[N] , e[N];
int f[N];
void fft(data *a , int n , int flag)
{
int i , j , k;
for(i = k = 0 ; i < n ; i ++ )
{
if(i > k) swap(a[i] , a[k]);
for(j = (n >> 1) ; (k ^= j) < j ; j >>= 1);
}
for(k = 2 ; k <= n ; k <<= 1)
{
data wn(cos(2 * pi * flag / k) , sin(2 * pi * flag / k));
for(i = 0 ; i < n ; i += k)
{
data t , w(1 , 0);
for(j = i ; j < i + (k >> 1) ; j ++ , w = w * wn)
t = w * a[j + (k >> 1)] , a[j + (k >> 1)] = a[j] - t , a[j] = a[j] + t;
}
}
if(flag == -1)
for(i = 0 ; i < n ; i ++ )
a[i].x /= n;
}
int main()
{
int n , i , t , m = 0 , len;
scanf("%d" , &n);
while(n -- ) scanf("%d" , &t) , a[t].x ++ , b[t * 2].x ++ , c[t * 3].x ++ , d[t].x ++ , e[t * 2].x ++ , f[t] ++ ;
m = t * 3;
for(len = 1 ; len < m ; len <<= 1);
fft(a , len , 1) , fft(b , len , 1);
for(i = 0 ; i < len ; i ++ ) b[i] = b[i] * a[i] , a[i] = a[i] * a[i] * a[i];
fft(a , len , -1) , fft(b , len , -1);
fft(d , len , 1);
for(i = 0 ; i < len ; i ++ ) d[i] = d[i] * d[i];
fft(d , len , -1);
for(i = 1 ; i <= m ; i ++ )
if((ll)(a[i].x - 3 * b[i].x + 2 * c[i].x + 0.5) / 6 + (ll)(d[i].x - e[i].x + 0.5) / 2 + f[i])
printf("%d %lld\n" , i , (ll)(a[i].x - 3 * b[i].x + 2 * c[i].x + 0.5) / 6 + (ll)(d[i].x - e[i].x + 0.5) / 2 + f[i]);
return 0;
}

【bzoj3771】Triple FFT+容斥原理的更多相关文章

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

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

  2. BZOJ 3771 Triple FFT+容斥原理

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

  3. BZOJ3771 Triple(FFT+容斥原理)

    思路比较直观.设A(x)=Σxai.先把只选一种的统计进去.然后考虑选两种,这个直接A(x)自己卷起来就好了,要去掉选同一种的情况然后除以2.现在得到了选两种的每种权值的方案数,再把这个卷上A(x). ...

  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. POJ 3734 Blocks (线性递推)

    定义ai表示红色和绿色方块中方块数为偶数的颜色有i个,i = 0,1,2. aij表示刷到第j个方块时的方案数,这是一个线性递推关系. 可以构造递推矩阵A,用矩阵快速幂求解. /*********** ...

  2. 2019年5~6月训练记录(更新ing)

    前言 \(ZJOI\)正式结束了. 但期中考试只考了年级\(216\),退役既视感... 于是就被抓回去补文化课了. 下半个学期可能要以文化课为主了吧! 但周三.周日应该还是会正常参加训练的,但其他时 ...

  3. iptables 防火墙详解

    一:前言   防火墙,其实说白了讲,就是用于实现Linux下访问控制的功能的,它分为硬件的或者软件的防火墙两种.无论是在哪个网络中,防火墙工作的地方一定是在网络的边缘.而我们的任务就是需要去定义到底防 ...

  4. 5分钟了解Java 12 八大新特性

    Java 12 终于发布了,我们一起来看一看 Java 12 中的新特性.通过本文可以在5分钟内快速了解 Java 12 新特性. 1 Switch 表达式 使用Java 12,switch不仅可以作 ...

  5. python_47_Python2中字符编码与转码

    #python3默认是Unicode,Unicode是万国码,不管中文字符还是英文,所有的每个字符都占2个字节空间,16位 #python2默认是ascii码 #ascii码不能存中文,一个英文只能占 ...

  6. react安装极其了解

    全局安装react脚手架工具 首先全局进行安装:cnpm install create-react-app -g 查看是否安装完成:create-react-app 创建react项目:create- ...

  7. abs的个人博客 http://abs001.top/blog

    abs的个人博客 abs的个人博客 abs的个人博客 abs的个人博客 abs的个人博客 abs的个人博客 abs的个人博客 abs的个人博客 abs的个人博客 abs的个人博客 abs的个人博客 a ...

  8. pycharm clion rider 注册

    JetBrains 公司出品的pycharm clion rider 专业版本都需要注册才能运行,这里有个免费注册方法: JetBrains授权服务器2017.10.7授权方法:激活时选择Licens ...

  9. JZOJ 4757. 树上摩托

    Description Sherco是一位经验丰富的魔♂法师.Sherco在第零次圣杯战争中取得了胜利,并取得了王之宝藏——王の树.他想把这棵树砍去任意条边,拆成若干棵新树,并装饰在他的摩托上,让他的 ...

  10. oop 单例模式