CodeForces 958F3 Lightsabers (hard) 启发式合并/分治 多项式 FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8835443.html
题目传送门 - CodeForces 958F3
题意
有$n$个球,球有$m$种颜色,分别编号为$1\cdots m$,现在让你从中拿$k$个球,问拿到的球的颜色所构成的可重集合有多少种不同的可能。
注意同种颜色球是等价的,但是两个颜色为$x$的球不等价于一个。
$1\leq n\leq 2\times 10^5,\ \ \ \ \ 1\leq m,k\leq n$。
题解
来自Helvetic Coding Contest 2018 online mirror.
比赛的时候太蠢了只yy了个分治$FFT$,只有25分钟不敢写(其实说不定来得及,赛后写启发式合并不到20分钟A了(不过看了组数据(某种颜色出现次数为$0$的特殊情况)))。
分治$FFT$不讲,常数大容易被卡掉。
更好的做法是启发式合并。
考虑颜色集合S的计算结果为$a_{0\cdots x}$,其中$a_i$表示取$i$个球得到的不同结果数。
当合并两个颜色集合的时候,新的结果为:
$$c_i=\sum_{j=0}^{i}a_jb_{i-j}$$
显然就是一个多项式卷积直接$FFT$即可。
初始情况就是对于每一个颜色,设$cnt_i$为颜色$i$的出现次数,那么该颜色下标范围为$0\cdots cnt_i$,值全部为$1$。
然后我们只需要启发式合并几下就可以了。
启发式合并用小根堆来维护$vector$,保存的是编号,关键字是$.size()$,用$vector$来存储计算结果防$MLE$。
注意再开始的时候处理掉某种颜色出现次数为$0$的情况,不然会挂。
时间复杂度$O(n\log^2 n)$。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1<<18,mod=1009;
double PI=acos(-1.0);
int n,m,k,tot[N];
struct C{
double r,i;
C(){}
C(double a,double b){r=a,i=b;}
C operator + (C x){return C(r+x.r,i+x.i);}
C operator - (C x){return C(r-x.r,i-x.i);}
C operator * (C x){return C(r*x.r-i*x.i,r*x.i+i*x.r);}
}w[N],A[N],B[N];
int R[N];
vector <int> colors[N<<1];
struct cmp{
bool operator ()(int a,int b){
return colors[a].size()>colors[b].size();
}
};
priority_queue <int,vector<int>,cmp> heap;
void FFT(C a[],int n){
for (int i=0;i<n;i++)
if (i<R[i])
swap(a[i],a[R[i]]);
for (int t=n>>1,d=1;d<n;d<<=1,t>>=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
C tmp=w[t*j]*a[i+j+d];
a[i+j+d]=a[i+j]-tmp;
a[i+j]=a[i+j]+tmp;
}
}
void FFT_times(vector <int> &a,vector <int> &b,vector <int> &c){
int n,d;
for (int i=0;i<a.size();i++)
A[i]=C(a[i],0);
for (int i=0;i<b.size();i++)
B[i]=C(b[i],0);
for (n=1,d=0;n<a.size()+b.size()-1;n<<=1,d++);
for (int i=0;i<n;i++){
R[i]=(R[i>>1]>>1)|((i&1)<<(d-1));
w[i]=C(cos(2*PI*i/n),sin(2*PI*i/n));
}
for (int i=a.size();i<n;i++)
A[i]=C(0,0);
for (int i=b.size();i<n;i++)
B[i]=C(0,0);
FFT(A,n),FFT(B,n);
for (int i=0;i<n;i++)
A[i]=A[i]*B[i],w[i].i*=-1.0;
FFT(A,n);
c.clear();
for (int i=0;i<=a.size()+b.size()-2;i++)
c.push_back(((LL)(A[i].r/n+0.5))%mod);
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for (int i=1,x;i<=n;i++)
scanf("%d",&x),tot[x]++;
while (!heap.empty())
heap.pop();
int size=0;
for (int i=1;i<=m;i++){
if (tot[i]==0)
continue;
colors[++size].clear();
for (int j=0;j<=tot[i];j++)
colors[size].push_back(1);
heap.push(size);
}
while (heap.size()>=2){
int x=heap.top();
heap.pop();
int y=heap.top();
heap.pop();
FFT_times(colors[x],colors[y],colors[++size]);
colors[x].clear(),colors[y].clear();
heap.push(size);
}
printf("%d",colors[size][k]);
return 0;
}
CodeForces 958F3 Lightsabers (hard) 启发式合并/分治 多项式 FFT的更多相关文章
- Codeforces 965E Short Code 启发式合并 (看题解)
Short Code 我的想法是建出字典树, 然后让后面节点最多的点优先向上移到不能移为止, 然后gg. 正确做法是对于当前的节点如果没有被占, 那么从它的子树中选出一个深度最大的点换到当前位置. 用 ...
- codeforces 600E. Lomsat gelral 启发式合并
题目链接 给一颗树, 每个节点有初始的颜色值. 1为根节点.定义一个节点的值为, 它的子树中出现最多的颜色的值, 如果有多种颜色出现的次数相同, 那么值为所有颜色的值的和. 每一个叶子节点是一个map ...
- Lomsat gelral CodeForces - 600E (树上启发式合并)
You are given a rooted tree with root in vertex 1. Each vertex is coloured in some colour. Let's cal ...
- UOJ#23. 【UR #1】跳蚤国王下江南 仙人掌 Tarjan 点双 圆方树 点分治 多项式 FFT
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ23.html 题目传送门 - UOJ#23 题意 给定一个有 n 个节点的仙人掌(可能有重边). 对于所有 ...
- BZOJ3451 Tyvj1953 Normal 点分治 多项式 FFT
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3451.html 题目传送门 - BZOJ3451 题意 给定一棵有 $n$ 个节点的树,在树上随机点分 ...
- Codeforces 438E. The Child and Binary Tree 多项式,FFT
原文链接www.cnblogs.com/zhouzhendong/p/CF438E.html 前言 没做过多项式题,来一道入门题试试刀. 题解 设 $a_i$ 表示节点权值和为 $i$ 的二叉树个数, ...
- BZOJ4836 [Lydsy1704月赛]二元运算 分治 多项式 FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8830036.html 题目传送门 - BZOJ4836 题意 定义二元运算$opt$满足 $$x\ opt\ y ...
- Educational Codeforces Round 2 E. Lomsat gelral 启发式合并map
E. Lomsat gelral Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/600/prob ...
- codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(启发式合并)
codeforces 741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...
随机推荐
- linux 定时下载github最新代码
场景:网站的代码在github上托管,静态网站部署在服务器上,每次自己修改完本地代码后,提交到github上,需要自己去服务器上执行git pull 拉取最新代码, 为了解决这种操作,自己再服务器上 ...
- Js元素拖拽功能实现
Js元素拖拽功能实现 需要解决的问题 最近项目遇到了一个问题,就是用户某个操作需要弹出一个自定义的内容输入框,但是有个缺点,当浏览太大的时候没办法点击确认和取消按钮,应为这个弹出框是采用绝对定位的,取 ...
- NOI2018游记
Day-1 下午报道,没什么好说的 Day0 先考笔试,开幕式咕到了下午 笔试没什么好说的,反正都是 \(100\) 好像有很多人被gedit坑了? 下午开幕式,很多省的口号都有意思,比如: &quo ...
- mybatis操作mysql的奇淫技巧总结(代码库)
1.添加公共sql代码段 使用<sql> 和 <include> 标签 <sql id="userSubassemblyRecordParam"> ...
- vue数组中对象属性变化页面不渲染问题
问题引入 Vue之所以能够监听Model状态的变化,是因为JavaScript语言本身提供了Proxy或者Object.observe()机制来监听对象状态的变化.但是,对于数组元素的赋值,却没有办法 ...
- 洛谷P1258 小车问题(题解)
https://www.luogu.org/problemnew/show/P1258(题目传送) 看题的第一眼就把题归为二分题,一直向着二分的方向走,却忽略了数学的推理.推理一番后(看了题解),发现 ...
- es6常用的
常用: let关键字: 1. 作用: * 与var类似, 用于声明一个变量2. 特点: * 在块作用域内有效 * 不能重复声明 * 不会预处理, 不存在提升3. 应用: * 循环遍历加监听 * 使用l ...
- SpringCloud笔记四:Ribbon
目录 什么是Ribbon? Ribbon的配置 Maven引入 开启注解 Ribbon负载均衡 新建provider8002和8003 Ribbon核心组件IRule Ribbon自定义 什么是Rib ...
- javaScript事件机制深入学习(事件冒泡,事件捕获,事件绑定方式,移除事件方式,阻止浏览器默认行为,事件委托,模拟浏览器事件,自定义事件)
前言 JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间.可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码.这种在传统软 ...
- win2003 创建nds辅助服务器 步骤
准备条件:win2003系统DNS主机 win2003系统 DNS副机 在同一局域网下: 目标.新建个laohu.com 主机并添加副机 再 正向查找区域 右键新建区域---下一步--- 选择主要区 ...