Time Limit: 20 Sec  Memory Limit: 64 MB
Submit: 911  Solved: 528
[Submit][Status][Discuss]

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

Source

应该不难看出是生成函数

我们用$A(x) = a + bx^1 + cx^2 + \dots $表示价值为$1$的方案为$a$,价值为$2$的方案为$b$

那么很显然的思路就是:$A(x) + \frac{A(x) * A(x)}{2!} + \frac{A(x) * A(x) * A(x)}{3!}$

但是题目中要求了每种斧子只能拿一次,这样会多计算重复拿的一部分

因此我们考虑用容斥的方法将他们减去

定义$B(x) = x ^ i$表示价值为$i$的拿了两把的方案数

$C(x) = x ^ i$表示价值为$i$的拿了三把的方案数

拿两把斧子时会计算到$(x, x)$这种情况,所以拿两把时应该为$\frac{A(x) * A(x) - B(x)}{2!}$

拿三把时有些复杂

我们需要减去$(x, x, x)$和$(x, y, y)$这两种情况

第一种情况就是$C(x)$

第二种情况可以通过$A(x)* B(x)$计算得到,但此时也计算上了$(x, x, x)$这种情况

$(x, y, y)$有三种组合排列方式,所以要乘$3$,但$(x, x, x)$只有一种排列方式,所以最终统计答案时要加上$2 * C(x)$

最终的答案就是

$A + \frac{A * A - B}{2!} + \frac{A * A * A - 3 * A * B + 2C}{3!}$

多项式乘法可以用NTT,不过模数会炸998244353

看到大佬们都用FFT A了,那我就偷个懒喽

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<cmath>
  5. //#include<iostream>
  6. const double pi = acos(-);
  7. using namespace std;
  8. const int MAXN = ;
  9. inline int read() {
  10. char c = getchar(); int x = , f = ;
  11. while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
  12. while(c >= '' && c <= '') x = x * + c - '', c = getchar();
  13. return x * f;
  14. }
  15. struct complex {
  16. double x, y;
  17. complex(double xx = , double yy = ) {x = xx, y = yy;}
  18. complex operator + (const complex &rhs) {
  19. return complex(x + rhs.x, y + rhs.y);
  20. }
  21. complex operator - (const complex &rhs) {
  22. return complex(x - rhs.x, y - rhs.y);
  23. }
  24. complex operator * (const complex &rhs) {
  25. return complex(x * rhs.x - y * rhs.y, x * rhs.y + y * rhs.x);
  26. }
  27. complex operator * (const double &rhs) {
  28. return complex(x * rhs, y * rhs);
  29. }
  30. complex operator / (const double &rhs) {
  31. return complex(x / rhs, y / rhs);
  32. }
  33. }A[MAXN], B[MAXN], C[MAXN];
  34. int val, n, N, L, len, r[MAXN];
  35. void FFT(complex *A, int type) {
  36. for(int i = ; i < N; i++) if(i < r[i]) swap(A[i], A[r[i]]);
  37. for(int mid = ; mid < N; mid <<= ) {
  38. complex Wn(cos(pi / mid), type * sin(pi / mid));
  39. for(int j = ; j < N; j += (mid << )) {
  40. complex w = complex(, );
  41. for(int i = ; i < mid; i++, w = w * Wn) {
  42. complex x = A[j + i], y = w * A[j + i + mid];
  43. A[j + i] = x + y;
  44. A[j + i + mid] = x - y;
  45. }
  46. }
  47. }
  48. if(type == -) {
  49. for(int i = ; i < N; i++)
  50. A[i].x /= N;
  51. }
  52. }
  53. void print(complex *a) {
  54. for(int i = ; i < N; i++)
  55. printf("%d %lf %lf\n", i, a[i].x, a[i].y);
  56. }
  57. int main() {
  58. #ifdef WIN32
  59. freopen("a.in", "r", stdin);
  60. freopen("b.out", "w", stdout);
  61. #endif
  62. n = read();
  63. for(int i = ; i <= n; i++)
  64. val = read(),
  65. A[val].x = ,
  66. B[ * val].x = ,
  67. C[ * val].x = ,
  68. len = max( * val, len);
  69. len = len + ;//tag
  70. for(N = ; N <= len; N <<= , L++);
  71. for(int i = ; i < N; i++)
  72. r[i] = (r[i >> ] >> ) | ((i & ) << (L - ));
  73.  
  74. FFT(C, );
  75. FFT(A, );
  76. FFT(B, );
  77. for(int i = ; i < N; i++)
  78. A[i] = A[i] + (A[i] * A[i] - B[i]) / 2.0 + (A[i] * A[i] * A[i] - A[i] * B[i] * 3.0 + C[i] * 2.0) / 6.0;
  79. FFT(A, -);
  80.  
  81. for(int i = ; i < N; i++) {
  82. long long cur = (long long )(A[i].x + 0.5);
  83. if(cur)
  84. printf("%d %lld\n", i, cur);
  85. }
  86. return ;
  87. }

BZOJ 3771: Triple(生成函数 FFT)的更多相关文章

  1. BZOJ.3771.Triple(母函数 FFT 容斥)

    题目链接 \(Description\) 有\(n\)个物品(斧头),每个物品价值不同且只有一件,问取出一件.两件.三件物品,所有可能得到的价值和及其方案数.\((a,b),(b,a)\)算作一种方案 ...

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

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

  3. bzoj 3771 Triple FFT 生成函数+容斥

    Triple Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 847  Solved: 482[Submit][Status][Discuss] Desc ...

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

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

  5. BZOJ 3771: Triple [快速傅里叶变换 生成函数 容斥原理]

    题意:n个物品,可以用1/2/3个不同的物品组成不同的价值,求每种价值有多少种方案(顺序不同算一种) [生成函数]: 构造这么一个多项式函数g(x),使得n次项系数为a[n]. 普通型生成函数用于解决 ...

  6. bzoj 3771 Triple——FFT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3771 把方案作为系数.值作为指数,两项相乘就是系数相乘.指数相加,符合意义. 考虑去重.先自 ...

  7. bzoj 3771 Triple —— FFT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3771 令多项式的系数是方案数,次数是值: 设 a(x) 为一个物品的多项式,即 a[w[i] ...

  8. BZOJ 3771 Triple FFT+容斥原理

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

  9. BZOJ 3771 Triple ——FFT

    直接暴力卷积+统计就可以了. 去重比较复杂. 其实也不复杂,抄吧! 反正AC了. #include <map> #include <cmath> #include <qu ...

随机推荐

  1. Python3.5 使用Sqlite3

    -------------------- 修雨轩陈@cnblog Python3.5 使用Sqlite3 python3.5 安装的时候会有很多可选参数,这些参数是默认不提供的,可是当我们想通过pip ...

  2. KNN 与 K - Means 算法比较

    KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...

  3. Android中的this、Activity、Context等

    Android中的this.Activity.Context.Application等虽然有相似之处,但是不能乱用,每一个都有自己的特点.用的时候不能太随意了. 避免context相关的内存泄露,注意 ...

  4. mongodb 3.4 YUM安装

    1:配置yum源vi /etc/yum.repos.d/mongodb-org-3.4.repo加入以下内容: [mongodb-org-3.4] name=MongoDB Repository ba ...

  5. photoshopcs6破解补丁用来干嘛的

    photoshopcs6破解补丁为 Adobe CS6 系列软件通用破解补丁,亲测可用,终于能用了不再出现那个烦人的购买页面了,cs6破解补丁解压后得到32和64两个文件夹,根据自己的系统类型选择,6 ...

  6. 电脑断电后Everything部分文件搜索不到的解决办法

    常规检查:查看选项→索引→NTFS,确认所有分区都[包含到数据库],确认后,再删除数据库文件,点击[强制重建] 下面方法是亲身经历,是断电造成的,费了不少时间才解决,现分享出来: 断电后,Everyt ...

  7. Oracle sql trace用法

    sql_trace是oracle提供的一个非常好的跟踪工具,主要用来检查数据库的异常情况,通过跟踪数据库的活动,找到有问题的语句. 一.概述:    SQL_TRACE是Oracle的一个非常强大的工 ...

  8. SAP Customer Data Cloud(Gigya)的用户搜索实现

    我在Gigya前台根据email搜索,输入一个邮箱地址,回车,在Chrome开发者工具里观察到到后台的网络请求: 这是一个post请求: __RequestVerificationToken 请求体: ...

  9. 入职日志——Solomon

    心情 今天是所有培训结束后入职的第二天,紧张且期待. 紧张是因为昨天董经理有句话点醒了我. 你默默不再是个学生了.没有人会像你的老师父母一样担待你,原谅你. 职场是残酷无情的,是以结果为导向的.不论对 ...

  10. Oracle创建自增序列

    Oracle没有自增字段这样的功能,但是通过触发器(trigger)和序列(sequence)可以实现. 先建一个测试表了: create table userlogin( id   number(6 ...