@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\)。则答案:

\[G(x) = \sum_{i=1}^{n}i\times (Fa_i(x)(\sum_{j=i+1}^{n} Fb_j(x)) + Fb_i(x)(\sum_{j=i+1}^{n} Fa_j(x)) + Fa_i(x) Fb_i(x))
\]

不过这样算还不如暴力快。

注意到 \(\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的更多相关文章

  1. TopCoder kawigiEdit插件配置

    kawigiEdit插件可以提高 TopCoder编译,提交效率,可以管理保存每次SRM的代码. kawigiEdit下载地址:http://code.google.com/p/kawigiedit/ ...

  2. 记第一次TopCoder, 练习SRM 583 div2 250

    今天第一次做topcoder,没有比赛,所以找的最新一期的SRM练习,做了第一道题. 题目大意是说 给一个数字字符串,任意交换两位,使数字变为最小,不能有前导0. 看到题目以后,先想到的找规律,发现要 ...

  3. TopCoder比赛总结表

    TopCoder                        250                              500                                 ...

  4. Topcoder几例C++字符串应用

    本文写于9月初,是利用Topcoder准备应聘时的机试环节临时补习的C++的一部分内容.签约之后,没有再进行练习,此文暂告一段落. 换句话说,就是本文太监了,一直做草稿看着别扭,删掉又觉得可惜,索性发 ...

  5. TopCoder

    在TopCoder下载好luncher,网址:https://www.topcoder.com/community/competitive%20programming/ 选择launch web ar ...

  6. TopCoder SRM 596 DIV 1 250

    body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...

  7. 求拓扑排序的数量,例题 topcoder srm 654 div2 500

    周赛时遇到的一道比较有意思的题目: Problem Statement      There are N rooms in Maki's new house. The rooms are number ...

  8. TopCoder SRM 590

     第一次做TC,不太习惯,各种调试,只做了一题...... Problem Statement     Fox Ciel is going to play Gomoku with her friend ...

  9. Topcoder Arena插件配置和训练指南

    一. Arena插件配置 1. 下载Arena 指针:http://community.topcoder.com/tc?module=MyHome 左边Competitions->Algorit ...

随机推荐

  1. 一个文件搞定Asp.net core 3.1动态页面转静态页面

    最近一个Asp.net core项目需要静态化页面,百度查找了一下,没有发现合适的.原因如下 配置麻烦. 类库引用了第三方类,修改起来麻烦. 有只支持MVC,不支持PageModel. 继承Actio ...

  2. 从零开始搭建一个PaaS平台 - 我们要做什么

    前言 从最开始的小公司做小网站,到现在进入现在的公司做项目,发现小公司里很多很多工作都是重复的劳动(增删改查),不过想想也是,业务软件最基础的东西不就是增删改查吗. 但是很多时候,这种业务逻辑其实没有 ...

  3. 使用element-ui 的table 组件 出现表格线条不对齐的问题

    在全局css样式中添加以下代码即可: body .el-table th.gutter { display: table-cell !important }

  4. LNMP PHP升级脚本

    升级PHP前,请确认你的网站程序是否支持升级到的PHP版本,防止升级到网站程序不兼容的PHP版本,具体可以去你使用的PHP程序的官网查询相关版本支持信息.v1.3及以后版本大部分情况下也可以进行降级操 ...

  5. android自动化

    1.环境安装 JDK 1.8 Appium Android_SDK python https://www.cnblogs.com/xiaohanzi/p/10676720.html https://b ...

  6. Lambda表达式用法大比较: Scala和Java 8

    最近几年Lambda表达式风靡于编程界. 很多现代编程语言都把它作为函数式编程的基本组成部分. 基于JVM的编程语言如Scala,Groovy还有Clojure把它们作为关键部分集成在语言中.现在Ja ...

  7. 【JUC】阻塞队列&生产者和消费者

    阻塞队列 线程1往阻塞队列添加元素[生产者] 线程2从阻塞队列取出元素[消费者] 当队列空时,获取元素的操作会被阻塞 当队列满时,添加元素的操作会被阻塞 阻塞队列的优势:在多线程领域,发生阻塞时,线程 ...

  8. react中路由不起作用的奇怪现象

    同样的两段Router代码,为什么一段正常,一段不起作用(也没有任何错误log提示) 瞪着眼观察也看不出为什么... 通过选中高亮显示内容相同, 为何就是有一段路由不管用呢? 折腾半天发现... 大小 ...

  9. eatwhatApp开发实战(六)

    上次,我们为app添加了本地存储的功能,但会发现一但退出app则存储的商家集合就消失,但其实本地已经存储了记录只是没去读取罢了. 接下来我们来实现这个功能. /** * 获取本地数据 */ priva ...

  10. python3程序开发指南——第1章 笔记

    python文件的扩展名为.py ,但是python GUI程序的扩展名为.pyw 在python中,注释以#开始,作用范围为该行 IDLE提供了三个关键功能:输入python表达式与代码,并在pyt ...