题目大意:

给出\(n\)个互不相同的物品,每个物品有价值\(x_i(x_i \leq 40000)\)如果可以从中取一个或两个或三个物品。问能够组合出来的所有价值和对应的方案数,全部输出.取值时,\((a,b)\)和\((b,a)\)算作一种

题解:

不要说什没有给\(n\)的范围什么的,题目表明了\(n \leq 40000\)

我们首先想到的是直接取

我们构造出只取一个物品时的母函数

\[A(x) = x + x^2 + x^3 + ...
\]

然后我们取两个物品的时候的母函数就可以用乘积来表示

即\(A(x)*A(x)\)

但是我们发现这样取到了不合法的情况,每个物品只能取一遍,但是直接计算的话会出现同一个物品取了两次的情况

所以我们应该减去这个不合法的情况(即容斥原理)

什么是不合法情况呢?就是同一个物品被取到了两次.

所以我们构造出取同一个物品取了两次的母函数,即

\[B(x) = x^2 + x^4 + x^6 + ...
\]

所以我们取两个的方案数就是\(A(x)^2 - B(x)\)

相应的我们构造出同一个物品取了三次的母函数,即

\[C(x) = x^3 + x^6 + x^9 + ...
\]

所以我们考虑在取三个的时候我们取到的有\(AAB, ABA, BAA, AAA\)

所以由容斥原理,取三个的时候的方案即为\(A(x)^3 - 3A(x)B(x) + 2C(x)\)

但是我们都没有考虑顺序的问题,我们考虑顺去,除去所有元素的全排列

那么我们最终的答案就是

\[\frac{A(x)}{1!} + \frac{A(x)^2-B(x)}{2!} + \frac{A(x)^3 - 3A(x)B(x) + 2C(x)}{3!}
\]

使用FFT计算即可

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 208000;
const double pi = acos(-1);
struct complex{
double x,y;
complex(){}
complex(double a,double b){x=a;y=b;}
complex operator + (const complex &r){return complex(x+r.x,y+r.y);}
complex operator - (const complex &r){return complex(x-r.x,y-r.y);}
complex operator * (const complex &r){return complex(x*r.x-y*r.y,x*r.y+y*r.x);}
complex operator / (const double &r){return complex(x/r,y/r);}
};
void FFT(complex *x,int n,int p){
for(int i=0,t=0;i<n;++i){
if(i > t) swap(x[i],x[t]);
for(int j=n>>1;(t^=j) < j;j>>=1);
}
for(int m=2;m<=n;m<<=1){
complex wn(cos(p*2*pi/m),sin(p*2*pi/m));
for(int i=0;i<n;i+=m){
complex w(1,0),u;
int k = m>>1;
for(int j=0;j<k;++j,w=w*wn){
u = x[i+j+k]*w;
x[i+j+k] = x[i+j] - u;
x[i+j] = x[i+j] + u;
}
}
}
if(p == -1) for(int i=0;i<n;++i) x[i] = x[i]/n;
}
complex a[maxn],b[maxn],c[maxn],d[maxn];
int main(){
int n;read(n);
int nn = 0;
for(int i=0,x;i<n;++i){
read(x);
a[x].x += 1.0;
b[x<<1].x += 1.0;
c[x*3].x += 1.0;
nn = cat_max(nn,x*3);
}
int len = 1;
for(int i=1;(i>>1)<nn;i<<=1) len = i;
FFT(a,len,1);FFT(b,len,1);
for(int i=0;i<len;++i) d[i] = a[i]*a[i]*a[i]/6.0 + (a[i]*a[i] - a[i]*b[i] - b[i])/2.0 + a[i];
FFT(d,len,-1);
for(int i=0;i<len;++i) d[i] = d[i] + c[i]/3.0;
for(int i=0;i<len;++i){
int x = (int)(d[i].x + 0.5);
if(x == 0) continue;
printf("%d %d\n",i,x);
}
getchar();getchar();
return 0;
}

bzoj 3771: Triple 快速傅里叶变换 FFT的更多相关文章

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

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

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

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

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

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

  4. 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)

    再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...

  5. 快速傅里叶变换(FFT)学习笔记(其一)

    再探快速傅里叶变换(FFT)学习笔记(其一) 目录 再探快速傅里叶变换(FFT)学习笔记(其一) 写在前面 为什么写这篇博客 一些约定 前置知识 多项式卷积 多项式的系数表达式和点值表达式 单位根及其 ...

  6. 快速傅里叶变换FFT

    多项式乘法 #include <cstdio> #include <cmath> #include <algorithm> #include <cstdlib ...

  7. [学习笔记] 多项式与快速傅里叶变换(FFT)基础

    引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...

  8. 快速傅里叶变换FFT& 数论变换NTT

    相关知识 时间域上的函数f(t)经过傅里叶变换(Fourier Transform)变成频率域上的F(w),也就是用一些不同频率正弦曲线的加 权叠加得到时间域上的信号. \[ F(\omega)=\m ...

  9. 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】

    原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...

随机推荐

  1. Laravel 5.4---后端数据分页和前端显示分页结果

    后端数据(Eloquent 模型)分页 事先建立好Eloquent 模型和Controller 还有 前台的View.可以参考我之前的文章:Laravel建站03--建立前台文章列表和文章详情 在co ...

  2. easyNetq demo

    本demo包含一个类库,2个console程序 1.新建类库  MQHelper,控制台程序  consumer和proc ,控制台程序引用MQHelper 2.使用nuget安装easynwtq 和 ...

  3. eval(function(p,a,c,k,e,d){e=function(c)加解密

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. eclipse中三大利器

    eclipse中两大利器: 首先说下用eclipse开发工具.进行java代码,开发的时候,我们开发完成以后.需要测试.大部分我们用Junit测试工具.可是内部的代码覆盖率.和结构我们看的不是那么详细 ...

  5. mybatis--foreach,choose 小结

    写博客个人不喜欢写那种长篇大论.富有文採与哲学的文章,搞开发的就喜欢直击重点,仅仅记录重要的信息就好了,以后查看的时候也很方便! mybatis 中 在if语句或when中 假设推断一个字段是否和1同 ...

  6. whl文件下载

    到哪找.whl文件?http://www.lfd.uci.edu/~gohlke/pythonlibs/

  7. vscode webstrom 配置 eslint 使用 airbnb 规范

    1.安装eslint npm eslint-plugin-react eslint-plugin-import babel-eslint -g 2.全局配置文件,放到c:/user/***/ { &q ...

  8. Mybatis之增删改查操作

    准备工作 建立整体项目目录 新建一个java工程,创建如下工程目录 其中com.kang.pojo中存放pojo类,com.kang.test中存放测试类. 源码目录config中存放Mybatis的 ...

  9. 基于Flume的美团日志收集系统 架构和设计 改进和优化

    3种解决办法 https://tech.meituan.com/mt-log-system-arch.html 基于Flume的美团日志收集系统(一)架构和设计 - https://tech.meit ...

  10. Swift 学习笔记 (属性)

    属性可以将值与特定的类 结构体 或者枚举联系起来. 存储属性会存储常量或者变量作为实例的一部分.反之计算属性会计算(而不是存储值)值. 计算属性可以由类 结构体 和枚举定义.存储属性只能由类和结构体定 ...