题目大意

  有\(n\)把斧头,不同斧头的价值都不同且都是\([0,m]\)的整数。你可以选\(1\)~\(3\)把斧头,总价值为这三把斧头的价值之和。请你对于每种可能的总价值,求出有多少种选择方案。

  选\(2\)把斧头时,\((a,b)\)和\((b,a)\)视为一种方案。选\(3\)把斧头时,\((a,b,c),(b,c,a),(c,a,b),(c,b,a),(b,a,c),(a,c,b)\)视为一种方案。

  \(m\leq 40000\).

题解

  考虑生成函数。

​ 设\(X\)是每种斧头取一个的生成函数,\(Y\)是每种斧头取两个的生成函数,\(Z\)是每种斧头取三个的生成函数,\(A\)是只取一个斧头的答案的生成函数,\(B\)是取两个斧头的答案的生成函数,\(C\)是取三个斧头的答案的生成函数。

  容斥一下。

\[A=X\\
B=\frac{X^2-Y}2\\
C=\frac{X^3-3XY+2Z}6
\]

  我来讲解一下第三个式子

  下文中第一项代表\(X^3\),第二项代表\(XY\),第三项代表\(Z\)

  对于方案\((a,a,a)\),会在第一项中出现\(1\)次,在第二项中出现\(3\)次,在第三项中出现\(1\)次。

  对于方案\((a,a,b)\),会在第一项中出现\(3\)次,在第二项中出现\(1\)次,在第三项中出现\(0\)次。

  对于方案\((a,b,c)\),会在第一项中出现\(6\)次,在第二项中出现\(0\)次,在第三项中出现\(0\)次。

  这样\((a,a,a)\)和\((a,a,b)\)的贡献就会全部被消掉,所以答案是对的。

  然后用FFT加速。

  时间复杂度:\(O(m\log m)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
double pi=acos(-1);
int n=131072;
struct cp
{
double x,y;
cp(double a=0,double b=0)
{
x=a;
y=b;
}
};
cp operator +(cp a,cp b){return cp(a.x+b.x,a.y+b.y);}
cp operator -(cp a,cp b){return cp(a.x-b.x,a.y-b.y);}
cp operator *(cp a,cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
cp operator *(cp a,double b){return cp(a.x*b,a.y*b);}
cp operator /(cp a,double b){return cp(a.x/b,a.y/b);}
cp a[200010];
cp b[200010];
cp c[200010];
cp w1[200010];
cp w2[200010];
int rev[200010];
void fft(cp *a,int t)
{
int i,j,k;
cp w,wn,u,v;
for(i=0;i<n;i++)
if(rev[i]<i)
swap(a[i],a[rev[i]]);
for(i=2;i<=n;i<<=1)
{
wn=(t==1?w1[i]:w2[i]);
for(j=0;j<n;j+=i)
{
w=cp(1,0);
for(k=j;k<j+i/2;k++)
{
u=a[k];
v=a[k+i/2]*w;
a[k]=u+v;
a[k+i/2]=u-v;
w=w*wn;
}
}
}
if(t==-1)
for(i=0;i<n;i++)
a[i]=a[i]/n;
}
int main()
{
int i;
for(i=2;i<=n;i<<=1)
{
w1[i]=cp(cos(2*pi/i),sin(2*pi/i));
w2[i]=cp(cos(2*pi/i),-sin(2*pi/i));
}
rev[0]=0;
for(i=1;i<n;i++)
rev[i]=(rev[i>>1]>>1)|(i&1?n/2:0);
int m;
scanf("%d",&m);
int x;
for(i=1;i<=m;i++)
{
scanf("%d",&x);
a[x].x+=1;
b[2*x].x+=1;
c[3*x].x+=1;
}
fft(a,1);
fft(b,1);
fft(c,1);
for(i=0;i<n;i++)
a[i]=a[i]+(a[i]*a[i]-b[i])/2+(a[i]*a[i]*a[i]-a[i]*b[i]*3+c[i]*2)/6;
fft(a,-1);
for(i=0;i<n;i++)
{
ll s=round(a[i].x);
if(s>0)
printf("%d %lld\n",i,s);
}
return 0;
}

【BZOJ3771】Triple 生成函数 FFT 容斥原理的更多相关文章

  1. BZOJ3771 Triple(FFT+容斥原理)

    思路比较直观.设A(x)=Σxai.先把只选一种的统计进去.然后考虑选两种,这个直接A(x)自己卷起来就好了,要去掉选同一种的情况然后除以2.现在得到了选两种的每种权值的方案数,再把这个卷上A(x). ...

  2. 2018.12.31 bzoj3771: Triple(生成函数+fft+容斥原理)

    传送门 生成函数经典题. 题意简述:给出nnn个数,可以从中选1/2/31/2/31/2/3个,问所有可能的和对应的方案数. 思路: 令A(x),B(x),C(x)A(x),B(x),C(x)A(x) ...

  3. 【BZOJ3771】Triple 生成函数+FFT

    [BZOJ3771]Triple Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: “这把斧头,是不是你的?” 樵夫一看 ...

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

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

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

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

  6. SPOJ Triple Sums(FFT+容斥原理)

    # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream& ...

  7. 【bzoj3771】Triple FFT+容斥原理

    题目描述 樵夫的每一把斧头都有一个价值,不同斧头的价值不同.总损失就是丢掉的斧头价值和. 他想对于每个可能的总损失,计算有几种可能的方案. 注意:如果水神拿走了两把斧头a和b,(a,b)和(b,a)视 ...

  8. loj6570 毛毛虫计数(生成函数FFT)

    link 巨佬olinr的题解 <-- olinr很强 考虑生成函数 考虑直径上点数>=4的毛毛虫的直径,考虑直径中间那些节点以及他上面挂的那些点的EGF \(A(x)=\sum_{i\g ...

  9. The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力)

    The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力) 传送门:https://nanti.jisuanke.com/ ...

随机推荐

  1. Python全栈开发之路 【第三篇】:Python基础之字符编码和文件操作

    本节内容 一.三元运算 三元运算又称三目运算,是对简单的条件语句的简写,如: 简单条件语句: if 条件成立: val = 1 else: val = 2 改成三元运算: val = 1 if 条件成 ...

  2. 关于function和task的说明

    1.  关于函数function调用,总结两个要点: 1.  函数调用一般产生一个值,这个值被赋值给某个变量 2.  函数所返回的值只能是一个,不可以是多个,不能像C语言中采用指针的方式返回多个值.因 ...

  3. ElastichSearch漏洞

    Ubuntu服务器被黑经历(ElastichSearch漏洞) 起因 最近我们的一台Ubuntu阿里云服务器一直提示有肉鸡行为,提示了好几天,开始并没有关注,然后连续几天后发现应该是个大问题啊.很可能 ...

  4. Linux之hosts文件

    一.序言: 今天同事部署环境遇到问题, 原因1:修改了主机名,在/etc/hosts文件中加了3台集群的ip和主机名,但是将默认的前两行也改了,没注意看改了哪里, 现象: 1.zookeeper单台可 ...

  5. 【学习总结】【Java】Git学习-上传本地已有代码到GitHub

    < Git学成归来后的第一次实战 > 上传本地已有代码到GitHub 以之前学了一小半的Java基础教程代码为例 <深坑预警:在GitHub新建仓库那一步,不要勾选readme,不然 ...

  6. 【Python3练习题 025】 一个数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同

    [Python练习题 025] 一个5位数,判断它是不是回文数.即12321是回文数,个位与万位相同,十位与千位相同 x = input('请输入任意位数的数字:') if x == x[::-1]: ...

  7. React Native之微信分享(iOS Android)

    React Native之微信分享(iOS Android) 在使用React Native开发项目的时候,基本都会使用到微信好友或者微信朋友圈分享功能吧,那么今天我就带大家实现以下RN微信好友以及朋 ...

  8. C# Note3:大话Ninject

    前言 之所以研究Ninject,是因为初入职在开发XX项目的ComponentService部分时用到了它,一下子发现了它的强大.渐渐地发现在项目中,有时会用到优秀的第三方开源库,这些都是前人智慧的结 ...

  9. 在浏览器上安装 Vue Devtools工具

    Vue.js devtools是基于google chrome浏览器的一款调试vue.js应用的开发者浏览器扩展,可以在浏览器开发者工具下调试代码. 1)首先在github下载devtools源码,地 ...

  10. python爬虫之Anaconda安装

    Anaconda概述 Anaconda是一个用于科学计算的Python发行版,支持 Linux, Mac, Windows系统,提供了包管理与环境管理的功能,可以很方便地解决多版本python并存.切 ...