【题意】给定n个物品,价值为$a_i$,物品价格互不相同,求选一个或两个或三个的价值为x的方案数,输出所有存在的x和对应方案数。$ai<=40000$。

【算法】生成函数+FFT

【题解】要求价值为x的方案数,就定义价值为“大小”(即指数),方案数为“元素个数”(即系数),物品为“选择项”(即多项式)。

设$f(x)$表示选择一个物品,价值为x的方案数。

虽然很容易想到$f^3(x)$,但因为不能重复选物品所以必须去重。而且不容易在$f^3(x)$中表示出选一个或两个物品。

①选择一个物品的方案数:$f$

考虑$f^2$表示选择两个物品价值和为x的可重排列数

去重需要减去两个物品相同的情况,设$g(x)$表示选择两个相同物品价值和为x的方案数,显然g可以直接得到。(枚举每个物品,在价值*2的系数处+1)。

因为生成函数乘积在两个物品相同的时候实际上没有排列,所以要先减再去排列。

②选择两个物品的方案数:$\frac{f^2-g}{2}$

最后三个物品同理,设$h(x)$表示选择三个相同物品价值和为x的方案数,需要排除BAA,ABA,AAB,AAA的情况。

其中BAA,ABA,AAB相当于选择两个相同物品后再选一个物品(无论是否再相同),即$f*g$。

但这样会把AA重复减去三次,实际上只需要减去一次,所以容斥加回,即$h$。

③选择三个物品的方案数:$\frac{f^3-3*f*g+2*h}{2}$

复杂度O(n log n)。

注意:先将f,g,h进行DFT,全部计算答案后再进行IDFT,才能保证精度。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<complex>
#include<cmath>
using namespace std;
const int maxn=;
const double PI=acos(-);
int n,ans[maxn];
complex<double>f[maxn],g[maxn],h[maxn];
namespace fft{
complex<double>o[maxn],oi[maxn];
void init(int n){
for(int k=;k<n;k++)o[k]=complex<double>(cos(*PI*k/n),sin(*PI*k/n)),oi[k]=conj(o[k]);
}
void transform(complex<double>*a,int n,complex<double>*o){
int k=;
while((<<k)<n)k++;
for(int i=;i<n;i++){
int t=;
for(int j=;j<k;j++)if(i&(<<j))t|=(<<(k-j-));
if(i<t)swap(a[i],a[t]);
}
for(int l=;l<=n;l*=){
int m=l/;
for(complex<double>*p=a;p!=a+n;p+=l){
for(int i=;i<m;i++){
complex<double>t=p[i+m]*o[n/l*i];
p[i+m]=p[i]-t;
p[i]+=t;
}
}
}
}
void dft(complex<double>*a,int n){transform(a,n,o);}
void idft(complex<double>*a,int n){transform(a,n,oi);for(int i=;i<n;i++)a[i]/=n;}
}
int main(){
scanf("%d",&n);
int mx=,t;
for(int i=;i<n;i++){
scanf("%d",&t);
f[t].real();g[t*].real(),h[t*].real();
mx=max(mx,t*);
}
n=;
while(n<*mx+)n*=;
fft::init(n);
fft::dft(f,n);fft::dft(g,n);fft::dft(h,n);
complex<double>tmp2=(),tmp3=(),tmp6=();
for(int i=;i<n;i++)f[i]=(f[i]*f[i]*f[i]-tmp3*f[i]*g[i]+tmp2*h[i])/tmp6+(f[i]*f[i]-g[i])/tmp2+f[i];
fft::idft(f,n);
for(int i=;i<n;i++)ans[i]=(int)(floor(f[i].real()+0.5));
for(int i=;i<n;i++)if(ans[i])printf("%d %d\n",i,ans[i]);
return ;
}

【BZOJ】3771: Triple FTT+生成函数的更多相关文章

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

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

  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. BZOJ 3771: Triple [快速傅里叶变换 生成函数 容斥原理]

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

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

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

  6. BZOJ 3771: Triple

    Description 问所有三/二/一元组可能形成的组合. Sol FFT. 利用生成函数直接FFT一下,然后就是计算,计算的时候简单的容斥一下. 任意三个-3*两个相同的+2*全部相同的+任意两个 ...

  7. bzoj 3771 Triple——FFT

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

  8. bzoj 3771 Triple —— FFT

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

  9. BZOJ 3771 Triple FFT+容斥原理

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

随机推荐

  1. 奥特曼小分队之we are a team

    团队名称:奥特曼小分队 团队博客链接:http://cnblogs.com/ATMXFD 团队负责跑腿的:李全清 http://www.cnblogs.com/QuanQingli/ 团队成员: 孙乐 ...

  2. lilntcode-508-摆动排序

    508-摆动排序 给你一个没有排序的数组,请将原数组就地重新排列满足如下性质 nums[0] <= nums[1] >= nums[2] <= nums[3].... 注意事项 请就 ...

  3. texbbox,combobox设置属性

    --输入框 $("#xx").textbox('setValue','value');  //设置输入框的值 $('#xx').textbox('textbox').attr('r ...

  4. tftp 简要使用说明

    yum 安装:tftp    tftp-server (2)启动tftp   CentOS 6 service xinetd restart chkconfig tftp on     CentOS ...

  5. 如何给一块新硬盘安装grub,让它成为一个只有一个内核的系统

    (1)先关机 (2)添加一块硬盘 (3)将硬盘分区,/dev/sdb1为boot分区,/dev/sdb2为swap分区, /dev/sdb3为根分区 (4)调整/dev/sdb2的分区类型为82,指定 ...

  6. HTMLA内联框架

    <head> <meta charset="utf-8" /> <title>内联框架</title> </head> ...

  7. 【leetcode】300.Longest Increasing Subsequence

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  8. 【转】mysql force Index 强制索引

    其他强制操作,优先操作如下: mysql常用的hint 对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法.同样,在mysql里,也有类似的h ...

  9. Java容器深入浅出之String、StringBuffer、StringBuilder

    对字符串的花式处理一直是现代应用系统的主要操作之一,也是对Java基础知识考察的重要方面.事实上,Java字符串类的底层是通过数组来实现的.具体来说,String类是固定长度的数组,StringBuf ...

  10. WordPress忘记密码找回登录密码的四种行之有效的方法

    WordPress忘记密码找回登录密码的四种行之有效的方法 PS:20170214更新,感谢SuperDoge同学提供的方法,登入phpMyAdmin后,先从左边选自己的数据库,然后点上面的 SQL ...