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 ...
随机推荐
- Python3.5 使用Sqlite3
-------------------- 修雨轩陈@cnblog Python3.5 使用Sqlite3 python3.5 安装的时候会有很多可选参数,这些参数是默认不提供的,可是当我们想通过pip ...
- KNN 与 K - Means 算法比较
KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...
- Android中的this、Activity、Context等
Android中的this.Activity.Context.Application等虽然有相似之处,但是不能乱用,每一个都有自己的特点.用的时候不能太随意了. 避免context相关的内存泄露,注意 ...
- mongodb 3.4 YUM安装
1:配置yum源vi /etc/yum.repos.d/mongodb-org-3.4.repo加入以下内容: [mongodb-org-3.4] name=MongoDB Repository ba ...
- photoshopcs6破解补丁用来干嘛的
photoshopcs6破解补丁为 Adobe CS6 系列软件通用破解补丁,亲测可用,终于能用了不再出现那个烦人的购买页面了,cs6破解补丁解压后得到32和64两个文件夹,根据自己的系统类型选择,6 ...
- 电脑断电后Everything部分文件搜索不到的解决办法
常规检查:查看选项→索引→NTFS,确认所有分区都[包含到数据库],确认后,再删除数据库文件,点击[强制重建] 下面方法是亲身经历,是断电造成的,费了不少时间才解决,现分享出来: 断电后,Everyt ...
- Oracle sql trace用法
sql_trace是oracle提供的一个非常好的跟踪工具,主要用来检查数据库的异常情况,通过跟踪数据库的活动,找到有问题的语句. 一.概述: SQL_TRACE是Oracle的一个非常强大的工 ...
- SAP Customer Data Cloud(Gigya)的用户搜索实现
我在Gigya前台根据email搜索,输入一个邮箱地址,回车,在Chrome开发者工具里观察到到后台的网络请求: 这是一个post请求: __RequestVerificationToken 请求体: ...
- 入职日志——Solomon
心情 今天是所有培训结束后入职的第二天,紧张且期待. 紧张是因为昨天董经理有句话点醒了我. 你默默不再是个学生了.没有人会像你的老师父母一样担待你,原谅你. 职场是残酷无情的,是以结果为导向的.不论对 ...
- Oracle创建自增序列
Oracle没有自增字段这样的功能,但是通过触发器(trigger)和序列(sequence)可以实现. 先建一个测试表了: create table userlogin( id number(6 ...