BZOJ 3771: Triple(生成函数 FFT)
Time Limit: 20 Sec Memory Limit: 64 MB
Submit: 911 Solved: 528
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4
5
6
7
Sample Output
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了,那我就偷个懒喽
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<iostream>
const double pi = acos(-);
using namespace std;
const int MAXN = ;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
struct complex {
double x, y;
complex(double xx = , double yy = ) {x = xx, y = yy;}
complex operator + (const complex &rhs) {
return complex(x + rhs.x, y + rhs.y);
}
complex operator - (const complex &rhs) {
return complex(x - rhs.x, y - rhs.y);
}
complex operator * (const complex &rhs) {
return complex(x * rhs.x - y * rhs.y, x * rhs.y + y * rhs.x);
}
complex operator * (const double &rhs) {
return complex(x * rhs, y * rhs);
}
complex operator / (const double &rhs) {
return complex(x / rhs, y / rhs);
}
}A[MAXN], B[MAXN], C[MAXN];
int val, n, N, L, len, r[MAXN];
void FFT(complex *A, int type) {
for(int i = ; i < N; i++) if(i < r[i]) swap(A[i], A[r[i]]);
for(int mid = ; mid < N; mid <<= ) {
complex Wn(cos(pi / mid), type * sin(pi / mid));
for(int j = ; j < N; j += (mid << )) {
complex w = complex(, );
for(int i = ; i < mid; i++, w = w * Wn) {
complex x = A[j + i], y = w * A[j + i + mid];
A[j + i] = x + y;
A[j + i + mid] = x - y;
}
}
}
if(type == -) {
for(int i = ; i < N; i++)
A[i].x /= N;
}
}
void print(complex *a) {
for(int i = ; i < N; i++)
printf("%d %lf %lf\n", i, a[i].x, a[i].y);
}
int main() {
#ifdef WIN32
freopen("a.in", "r", stdin);
freopen("b.out", "w", stdout);
#endif
n = read();
for(int i = ; i <= n; i++)
val = read(),
A[val].x = ,
B[ * val].x = ,
C[ * val].x = ,
len = max( * val, len);
len = len + ;//tag
for(N = ; N <= len; N <<= , L++);
for(int i = ; i < N; i++)
r[i] = (r[i >> ] >> ) | ((i & ) << (L - )); FFT(C, );
FFT(A, );
FFT(B, );
for(int i = ; i < N; i++)
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;
FFT(A, -); for(int i = ; i < N; i++) {
long long cur = (long long )(A[i].x + 0.5);
if(cur)
printf("%d %lld\n", i, cur);
}
return ;
}
BZOJ 3771: Triple(生成函数 FFT)的更多相关文章
- BZOJ.3771.Triple(母函数 FFT 容斥)
题目链接 \(Description\) 有\(n\)个物品(斧头),每个物品价值不同且只有一件,问取出一件.两件.三件物品,所有可能得到的价值和及其方案数.\((a,b),(b,a)\)算作一种方案 ...
- [BZOJ 3771] Triple(FFT+容斥原理+生成函数)
[BZOJ 3771] Triple(FFT+生成函数) 题面 给出 n个物品,价值为别为\(w_i\)且各不相同,现在可以取1个.2个或3个,问每种价值和有几种情况? 分析 这种计数问题容易想到生成 ...
- bzoj 3771 Triple FFT 生成函数+容斥
Triple Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 847 Solved: 482[Submit][Status][Discuss] Desc ...
- bzoj 3771: Triple【生成函数+FFT+容斥原理】
瞎搞居然1A,真是吃鲸 n的范围只有聪明人能看见--建议读题3遍 首先看计数就想到生成函数,列出多项式A(x),然后分别考虑123 对于选一个的直接计数即可: 对于选两个的,\( A(x)^2 \), ...
- BZOJ 3771: Triple [快速傅里叶变换 生成函数 容斥原理]
题意:n个物品,可以用1/2/3个不同的物品组成不同的价值,求每种价值有多少种方案(顺序不同算一种) [生成函数]: 构造这么一个多项式函数g(x),使得n次项系数为a[n]. 普通型生成函数用于解决 ...
- bzoj 3771 Triple——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3771 把方案作为系数.值作为指数,两项相乘就是系数相乘.指数相加,符合意义. 考虑去重.先自 ...
- bzoj 3771 Triple —— FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3771 令多项式的系数是方案数,次数是值: 设 a(x) 为一个物品的多项式,即 a[w[i] ...
- BZOJ 3771 Triple FFT+容斥原理
解析: 这东西其实就是指数型母函数? 所以刚开始读入的值我们都把它前面的系数置为1. 然后其实就是个多项式乘法了. 最大范围显然是读入的值中的最大值乘三,对于本题的话是12W? 用FFT优化的话,达到 ...
- BZOJ 3771 Triple ——FFT
直接暴力卷积+统计就可以了. 去重比较复杂. 其实也不复杂,抄吧! 反正AC了. #include <map> #include <cmath> #include <qu ...
随机推荐
- Java基础重点知识之欣欣向然
题目: 第一题:二重循环: public class Text01 { //完成歌曲排序的效果 public static void main(String[] args) { String[] zi ...
- Sql-exec
--显示sql server现有的所有数据库 exec sp_helpdb --查看数据表设置的约束 exec sp_helpconstraint SubjectType --update selec ...
- 【阿里云产品公测】云引擎ACE公测感受
听说阿里云ACE开始公测了,怀着激动的心情赶紧试用了一下. 这是我用ACE做出来的效果:http://haoyuming.aliapp.com/ 大家点点看看啊 A*W/Q<~I :eSwX ...
- Tesseract-OCR-05-主要API功能介绍
Tesseract-05-主要API功能介绍 tesseract本身代码是由c/c++混编而成的,其中有用的简单的接口函数几乎都是在baseapi.h中 从其处理过程中,不难得出: 它还需要有一个im ...
- day22笔记
用户上传的文件要保存 保存在服务器上的media文件夹下,用户上传的文件很多,所以需要分目录进行存放具体步骤 settings.pyMEDIA_URL="/media/"MEDIA ...
- javax.swing.JComponent 调用顺序
网上截取的,感觉挺有用,记录下来. http://bbs.csdn.net/topics/310041707 java swing 感觉好复杂啊…………一点都不想用但是作业要用到 >_<; ...
- easyui学习笔记8—在手风琴中加载其他的页面
在手风琴中加载其他页面和在表格中加载其他的页面有写类似的,就是请求另外一个页面显示数据. 1.先看看引用的资源文件 <link rel="stylesheet" href=& ...
- [原]Linux 命令行 发送邮件
1.mail -s hi xx@yy.com 给xx@yy.com发一封主题为hi的信(没有正文) 编辑完内容后Ctrl-D结束. 2.echo "This is a test mail!& ...
- ROC曲线手画
绘图过程很简单:给定m个正例子,n个反例子,根据学习器预测结果进行排序,先把分类阈值设为最大,使得所有例子均预测为反例,此时TPR和FPR均为0,在(0,0)处标记一个点,再将分类阈值依次设为每个样例 ...
- stl sort使用不当造成崩溃
#include <iostream>#include <vector>#include <algorithm>using namespace std; bool ...