Description

我们讲一个悲伤的故事。

从前有一个贫穷的樵夫在河边砍柴。

这时候河里出现了一个水神,夺过了他的斧头,说:

“这把斧头,是不是你的?”

樵夫一看:“是啊是啊!”

水神把斧头扔在一边,又拿起一个东西问:

“这把斧头,是不是你的?”

樵夫看不清楚,但又怕真的是自己的斧头,只好又答:“是啊是啊!”

水神又把手上的东西扔在一边,拿起第三个东西问:

“这把斧头,是不是你的?”

樵夫还是看不清楚,但是他觉得再这样下去他就没法砍柴了。

于是他又一次答:“是啊是啊!真的是!”

水神看着他,哈哈大笑道:

“你看看你现在的样子,真是丑陋!”

之后就消失了。

樵夫觉得很坑爹,他今天不仅没有砍到柴,还丢了一把斧头给那个水神。

于是他准备回家换一把斧头。

回家之后他才发现真正坑爹的事情才刚开始。

水神拿着的的确是他的斧头。

但是不一定是他拿出去的那把,还有可能是水神不知道怎么偷偷从他家里拿走的。

换句话说,水神可能拿走了他的一把,两把或者三把斧头。

樵夫觉得今天真是倒霉透了,但不管怎么样日子还得过。

他想统计他的损失。

樵夫的每一把斧头都有一个价值,不同斧头的价值不同。总损失就是丢掉的斧头价值和。

他想对于每个可能的总损失,计算有几种可能的方案。

注意:如果水神拿走了两把斧头a和b,(a,b)和(b,a)视为一种方案。拿走三把斧头时,(a,b,c),(b,c,a),(c,a,b),(c,b,a),(b,a,c),(a,c,b)视为一种方案。

Input

第一行是整数N,表示有N把斧头。

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

Output

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

Sample Input

4

4

5

6

7

Sample Output

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

样例解释

11有两种方案是4+7和5+6,其他损失值都有唯一方案,例如4=4,5=5,10=4+6,18=5+6+7.

HINT

所有数据满足:Ai<=40000


思路

考虑一个两个三个分别的生成函数

容斥掉不合法贡献


#include<bits/stdc++.h>

using namespace std;

const int N = 3e5 + 10;
const double eps = 1e-6;
const double PI = acos(-1); typedef complex<double> Complex; Complex f[N], g[N], h[N], p[N], q[N], w[N][2]; void init() {
for (int i = 1; i < (1 << 18); i <<= 1) {
w[i][0] = w[i][1] = Complex(1, 0);
Complex wn(cos(PI / i), sin(PI / i));
for (int j = 1; j < i; j++)
w[i + j][1] = w[i + j - 1][1] * wn;
wn = Complex(cos(PI / i), -sin(PI / i));
for (int j = 1; j < i; j++)
w[i + j][0] = w[i + j - 1][0] * wn;
}
} void transform(Complex t[N], int len, int typ) {
for (int i = 0, j = 0, k; j < len; j++) {
if (i > j) swap(t[i], t[j]);
for (k = (len >> 1); k & i; k >>= 1) i ^= k;
i ^= k;
}
for (int i = 1; i < len; i <<= 1) {
for (int j = 0; j < len; j += (i << 1)) {
for (int k = 0; k < i; k++) {
Complex x = t[j + k], y = t[j + k + i] * w[i + k][typ];
t[j + k] = x + y;
t[j + k + i] = x - y;
}
}
}
if (typ) return;
for (int i = 0; i < len; i++)
t[i] = Complex(t[i].real() / (double) len, t[i].imag());
} int n, a[N]; int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
#endif
init();
int maxval = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
maxval = max(maxval, a[i]);
}
maxval = maxval * 3 + 1;
for (int i = 1; i <= n; i++) {
f[a[i]] = Complex(f[a[i]].real() + 1, f[a[i]].imag());
p[a[i] * 2] = Complex(p[a[i] * 2].real() + 1, p[a[i] * 2].imag());
q[a[i] * 3] = Complex(q[a[i] * 3].real() + 1, q[a[i] * 3].imag());
}
int len = 1 << (int) ceil(log2(maxval * 2 - 1));
transform(f, len, 1);
for (int i = 0; i < len; i++)
g[i] = f[i] * f[i];
transform(g, len, 0);
for (int i = 0; i < len; i++)
g[i] -= p[i];
transform(g, len, 1);
for (int i = 0; i < len; i++)
h[i] = f[i] * f[i] * f[i];
transform(h, len, 0);
transform(p, len, 1);
for (int i = 0; i < len; i++)
p[i] = f[i] * p[i];
transform(g, len, 0);
transform(f, len, 0);
transform(p, len, 0);
for (int i = 0; i <= len; i++) {
h[i] -= p[i] + p[i] + p[i];
h[i] += q[i] + q[i];
}
for (int i = 0; i <= maxval; i++)
if ((int) (round(f[i].real()) + round(g[i].real()) / 2 + round(h[i].real()) / 6))
printf("%d %d\n", i, (int) (round(f[i].real()) + round(g[i].real()) / 2 + round(h[i].real()) / 6));
return 0;
}

BZOJ3771: Triple【生成函数】的更多相关文章

  1. 【BZOJ3771】Triple 生成函数+FFT

    [BZOJ3771]Triple Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: “这把斧头,是不是你的?” 樵夫一看 ...

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

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

  3. 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) ...

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

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

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

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

  6. BZOJ3771 Triple 【NTT + 容斥】

    题目链接 BZOJ3771 题解 做水题放松一下 先构造\(A_i\)为\(x\)指数的生成函数\(A(x)\) 再构造\(2A_i\)为指数的生成函数\(B(x)\) 再构造\(3A_i\)为指数的 ...

  7. BZOJ 3771: Triple(生成函数 FFT)

    Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 911  Solved: 528[Submit][Status][Discuss] Description ...

  8. BZOJ3771: Triple

    额我不是来发题解的,只是非常郁闷= =,这题的答案最大是1.2e9/6左右,所以用ntt的话要在模意义下除以6,不能最后除,否则刚好爆掉= = #include<bits/stdc++.h> ...

  9. $FFT/NTT/FWT$题单&简要题解

    打算写一个多项式总结. 虽然自己菜得太真实了. 好像四级标题太小了,下次写博客的时候再考虑一下. 模板 \(FFT\)模板 #include <iostream> #include < ...

随机推荐

  1. 什么是分布式锁?Redis实现分布式锁详解

    在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务.分布式锁等.那具体什么是分布式锁,分布式锁应用在哪些业务场景.如何来实现分布式锁呢?今天继续由陈睿|mikeche ...

  2. Observable类API

    包java.util 类 Observable public class Observable extends Object 此类表示模型视图范例中的 observable 对象,或者说“数据”.可将 ...

  3. Freemarker 简介

    1.动态网页和静态网页差异 在进入主题之前我先介绍一下什么是动态网页,动态网页是指跟静态网页相对应的一种网页编程技术.静态网页,随着HTML代码的生成,页面的内容和显示效果就不会再发生变化(除非你修改 ...

  4. spring-cloud: eureka之:ribbon负载均衡配置(一)

    spring-cloud: eureka之:ribbon负载均衡配置(一) 比如我有: 一个eureka服务:8761 两个user用户服务: 7900/7901端口 一个movie服务:8010 1 ...

  5. AND Graph CodeForces - 987F (状压)

    链接 大意:给定$m$个数, 若$x\&y=0$, 则在$x$与$y$之间连一条无向边. 求无向图的连通块个数 暴力连边显然超时的, 可以通过辅助结点优化连边, 复杂度$O(n2^n)$ #i ...

  6. nyoj860(01变形)

    http://acm.nyist.net/JudgeOnline/problem.php?pid=860 又见01背包 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 ...

  7. spring--mvc用戶注册用户名验重

    spring--mvc用戶注册用户名验重 注册是验证用户名是否重复.post方法,当表单的用户名文本框失去焦点时,由ajax方法指定,进行@RequestMapping指定的url提交时调用的方法. ...

  8. Intel DAAL AI加速——支持从数据预处理到模型预测,数据源必须使用DAAL的底层封装库

    数据源加速见官方文档(必须使用DAAL自己的库): Data Management Numeric Tables Tensors Data Sources Data Dictionaries Data ...

  9. 白化whitening

    原文地址:http://blog.csdn.net/hjimce/article/details/50864602 作者:hjimce 一.相关理论     白化这个词,可能在深度学习领域比较常遇到, ...

  10. PHP:第一章——PHP中的魔术常量

    <?php //__LINE__输出常量所在的行 //echo __LINE__; //2.__FILE__常量返回文件的完整路径和文件名; //echo __FILE__; //3.__DIR ...