@topcoder - SRM603D1L3@ SumOfArrays
@desription@
给定两个长度为 n 的数列 A, B。现你可以将两数列重排列,然后对应项相加得到 C[i] = A[i] + B[i]。
问你所能构造的 C 中众数的最大出现次数,以及此时的众数。如果有多种方案,取最大的众数。
@solution@
记 \(cnta[i]\) 表示 \(i\) 在 A 中的出现次数,\(cntb[i]\) 表示 \(i\) 在 B 中的出现次数。则 p 在 C 中的最大出现次数为 \(\sum_{i=0}^{p}\min(cnta[i], cntb[p-i])\)。
注意到它长得特别像个卷积。我们记 \(Fa_i(x) = \sum_{p=0}^{MAX} [cnta[p] = i]x^{p}\),同理记 \(Fb_i(x) = \sum_{p=0}^{MAX} [cntb[p] = i]x^p\)。则答案:
\]
不过这样算还不如暴力快。
注意到 \(\sum cnta[i] = n\),也就是说如果 i 越大,满足 cnta[p] = i 的 p 会越少。
具体而言,A 中 cnta[p] ≥ K 有 \(O(\frac{n}{K})\) 个,B 中也有 \(O(\frac{n}{K})\)。那么我们可以枚举每一个可能的二元组暴力计算,时间复杂度为 \(O(\frac{n^2}{K^2})\)。
当 K 较大时,这个暴力算法相对于上面的卷积方法而言,其实是非常快的。
于是又到了喜闻乐见的复杂度平衡时间:对于 i < K,使用卷积计算,复杂度为 \(O(K\times MAX\times \log MAX)\);对于 i >= K,使用暴力枚举,复杂度为 \(O(\frac{n^2}{K^2})\)
因为 n 与 MAX 同阶,我们直接令 \(Kn\log n = \frac{n^2}{K^2}\),解得 \(K = (\frac{n}{\log n})^{\frac{1}{3}}\)。
然后总时间复杂度 \(O(n^{\frac{4}{3}}\times \log^{\frac{2}{3}}n )\),虽然看着挺糟不过其实挺优秀的。
@accepted code@
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int MOD = 998244353;
const int MAXN = (1 << 17);
const int K = 18;
const int G = 3;
inline int add(int x, int y) {return (x + y >= MOD ? x + y - MOD : x + y);}
inline int sub(int x, int y) {return (x - y < 0 ? x - y + MOD : x - y);}
inline int mul(int x, int y) {return 1LL * x * y % MOD;}
int pow_mod(int b, int p) {
int ret = 1;
for(int i=p;i;i>>=1,b=mul(b,b))
if( i & 1 ) ret = mul(ret, b);
return ret;
}
int w[22], iw[22];
void init() {
for(int i=0;i<22;i++) {
w[i] = pow_mod(G, (MOD - 1) / (1 << i));
iw[i] = pow_mod(w[i], MOD - 2);
}
}
int length(int n) {
int len; for(len = 1; len < n; len <<= 1);
return len;
}
void ntt(int *A, int n, int type) {
for(int i=0,j=0;i<n;i++) {
if( i < j ) swap(A[i], A[j]);
for(int k=(n>>1);(j^=k)<k;k>>=1);
}
for(int i=1;(1<<i)<=n;i++) {
int s = (1 << i), t = (s >> 1);
int u = (type == 1 ? w[i] : iw[i]);
for(int j=0;j<n;j+=s) {
for(int k=0,p=1;k<t;k++,p=mul(p,u)) {
int x = A[j+k], y = mul(p, A[j+k+t]);
A[j+k] = add(x, y), A[j+k+t] = sub(x, y);
}
}
}
if( type == -1 ) {
int iv = pow_mod(n, MOD - 2);
for(int i=0;i<n;i++)
A[i] = mul(A[i], iv);
}
}
class SumOfArrays{
public:
vector<pair<int, int> >na, nb;
int f[2*MAXN + 5];
int ca[MAXN + 5], cb[MAXN + 5];
int a[MAXN + 5], b[MAXN + 5];
int ta1[2*MAXN + 5], ta2[2*MAXN + 5], tb1[2*MAXN + 5], tb2[2*MAXN + 5], tmp[2*MAXN + 5];
string findbestpair(int n, vector<int>A, vector<int>B) {
init();
a[0] = A[0], a[1] = A[1], b[0] = B[0], b[1] = B[1];
for(int i=2;i<n;i++) {
a[i] = (1LL*A[2]*a[i-1]%A[5] + 1LL*A[3]*a[i-2]%A[5] + A[4]) % A[5];
b[i] = (1LL*B[2]*b[i-1]%B[5] + 1LL*B[3]*b[i-2]%B[5] + B[4]) % B[5];
}
for(int i=0;i<n;i++)
ca[a[i]]++, cb[b[i]]++;
for(int i=0;i<MAXN;i++) {
if( ca[i] >= K ) na.push_back(make_pair(i, ca[i]));
if( cb[i] >= K ) nb.push_back(make_pair(i, cb[i]));
}
for(int i=0;i<(int)na.size();i++)
for(int j=0;j<(int)nb.size();j++)
f[na[i].first + nb[j].first] += min(na[i].second, nb[j].second);
for(int i=1;i<K;i++) {
bool flag = false;
for(int j=0;j<MAXN;j++) {
if( ca[j] > i ) ta1[j]++;
else if( ca[j] == i ) ta2[j]++, flag = true;
if( cb[j] > i ) tb1[j]++;
else if( cb[j] == i ) tb2[j]++, flag = true;
}
int len = 2*MAXN;
if( flag ) {
ntt(ta1, len, 1), ntt(ta2, len, 1), ntt(tb1, len, 1), ntt(tb2, len, 1);
for(int j=0;j<len;j++)
tmp[j] = add(add(mul(ta1[j], tb2[j]), mul(ta2[j], tb1[j])), mul(ta2[j], tb2[j]));
ntt(tmp, len, -1);
for(int j=0;j<len;j++)
f[j] = add(f[j], mul(tmp[j], i));
}
for(int j=0;j<len;j++) ta1[j] = ta2[j] = tb1[j] = tb2[j] = tmp[j] = 0;
}
int ans = 0, res;
for(int i=2*MAXN-1;i>=0;i--)
if( f[i] > ans ) ans = f[i], res = i;
string ret = "";
while( res ) ret = (char)(res % 10 + '0') + ret, res /= 10;
ret = " " + ret;
while( ans ) ret = (char)(ans % 10 + '0') + ret, ans /= 10;
return ret;
}
};
@details@
为什么要把函数返回值设置成这么反人类形式,还要把数转化成字符串。直接返回一个数组不挺好的。
@topcoder - SRM603D1L3@ SumOfArrays的更多相关文章
- TopCoder kawigiEdit插件配置
kawigiEdit插件可以提高 TopCoder编译,提交效率,可以管理保存每次SRM的代码. kawigiEdit下载地址:http://code.google.com/p/kawigiedit/ ...
- 记第一次TopCoder, 练习SRM 583 div2 250
今天第一次做topcoder,没有比赛,所以找的最新一期的SRM练习,做了第一道题. 题目大意是说 给一个数字字符串,任意交换两位,使数字变为最小,不能有前导0. 看到题目以后,先想到的找规律,发现要 ...
- TopCoder比赛总结表
TopCoder 250 500 ...
- Topcoder几例C++字符串应用
本文写于9月初,是利用Topcoder准备应聘时的机试环节临时补习的C++的一部分内容.签约之后,没有再进行练习,此文暂告一段落. 换句话说,就是本文太监了,一直做草稿看着别扭,删掉又觉得可惜,索性发 ...
- TopCoder
在TopCoder下载好luncher,网址:https://www.topcoder.com/community/competitive%20programming/ 选择launch web ar ...
- TopCoder SRM 596 DIV 1 250
body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...
- 求拓扑排序的数量,例题 topcoder srm 654 div2 500
周赛时遇到的一道比较有意思的题目: Problem Statement There are N rooms in Maki's new house. The rooms are number ...
- TopCoder SRM 590
第一次做TC,不太习惯,各种调试,只做了一题...... Problem Statement Fox Ciel is going to play Gomoku with her friend ...
- Topcoder Arena插件配置和训练指南
一. Arena插件配置 1. 下载Arena 指针:http://community.topcoder.com/tc?module=MyHome 左边Competitions->Algorit ...
随机推荐
- 一个文件搞定Asp.net core 3.1动态页面转静态页面
最近一个Asp.net core项目需要静态化页面,百度查找了一下,没有发现合适的.原因如下 配置麻烦. 类库引用了第三方类,修改起来麻烦. 有只支持MVC,不支持PageModel. 继承Actio ...
- 从零开始搭建一个PaaS平台 - 我们要做什么
前言 从最开始的小公司做小网站,到现在进入现在的公司做项目,发现小公司里很多很多工作都是重复的劳动(增删改查),不过想想也是,业务软件最基础的东西不就是增删改查吗. 但是很多时候,这种业务逻辑其实没有 ...
- 使用element-ui 的table 组件 出现表格线条不对齐的问题
在全局css样式中添加以下代码即可: body .el-table th.gutter { display: table-cell !important }
- LNMP PHP升级脚本
升级PHP前,请确认你的网站程序是否支持升级到的PHP版本,防止升级到网站程序不兼容的PHP版本,具体可以去你使用的PHP程序的官网查询相关版本支持信息.v1.3及以后版本大部分情况下也可以进行降级操 ...
- android自动化
1.环境安装 JDK 1.8 Appium Android_SDK python https://www.cnblogs.com/xiaohanzi/p/10676720.html https://b ...
- Lambda表达式用法大比较: Scala和Java 8
最近几年Lambda表达式风靡于编程界. 很多现代编程语言都把它作为函数式编程的基本组成部分. 基于JVM的编程语言如Scala,Groovy还有Clojure把它们作为关键部分集成在语言中.现在Ja ...
- 【JUC】阻塞队列&生产者和消费者
阻塞队列 线程1往阻塞队列添加元素[生产者] 线程2从阻塞队列取出元素[消费者] 当队列空时,获取元素的操作会被阻塞 当队列满时,添加元素的操作会被阻塞 阻塞队列的优势:在多线程领域,发生阻塞时,线程 ...
- react中路由不起作用的奇怪现象
同样的两段Router代码,为什么一段正常,一段不起作用(也没有任何错误log提示) 瞪着眼观察也看不出为什么... 通过选中高亮显示内容相同, 为何就是有一段路由不管用呢? 折腾半天发现... 大小 ...
- eatwhatApp开发实战(六)
上次,我们为app添加了本地存储的功能,但会发现一但退出app则存储的商家集合就消失,但其实本地已经存储了记录只是没去读取罢了. 接下来我们来实现这个功能. /** * 获取本地数据 */ priva ...
- python3程序开发指南——第1章 笔记
python文件的扩展名为.py ,但是python GUI程序的扩展名为.pyw 在python中,注释以#开始,作用范围为该行 IDLE提供了三个关键功能:输入python表达式与代码,并在pyt ...