@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. LightOJ1282

    题目大意: 给出 n 和 k,请你求出 n^k 次方的前三位和后三位. 解题思路: 后三位用快速幂,不加赘述. 求前三位的方法: AC代码: #include <iostream> #in ...

  2. 【百度网盘活动】扩容2T+7天会员

    https://pan.baidu.com/component/view?id=455 https://pan.baidu.com/union/smartProgramShare?scheme=bdn ...

  3. golang如何优雅的编写事务代码

    目录 前言 需求 烂代码示例 重构套路 一.提前返回去除if嵌套 二.goto+label提取重复代码 三.封装try-catch统一捕获panic 前言 新手程序员概有如下特点 if嵌套特别多.重复 ...

  4. Order by 优化

    写在前面 文章涉及到的 customer 表来源于案例库 sakila,下载地址为 http://downloads.mysql.com/docs/sakila-db.zip MySQL 排序方式 通 ...

  5. [Objective-C] Xcode中常用的快捷键操作与插件

    古人云“工欲善其事必先利其器”,打造和熟悉一个强大的开发环境,是每个程序员必须的! 在Xcode 6中有许多快捷键的设定可以使得你的编程工作更为高效,对于在代码文件中快速导航.定位Bug以及新增应用特 ...

  6. 对于使用progisp软件进行ISP编程时进入不了编程模式的解决方法

    标题: 对于使用progisp软件进行ISP编程时无法进入编程模式的解决方法 作者: 梦幻之心星 347369787@QQ.com 标签: [progisp, 软件] 目录: 软件 日期: 2019- ...

  7. 快速复习C语言 - 1变量与运算符

    变量与运算符 本篇以读者知道 int.char.float.double 等数据类型为前提条件. float 类型注意事项 float 类型数没有办法跟一个数真正比较是否相等,可以定义借助绝对值在一定 ...

  8. pip安装Python库速度慢的解决方法

    最近在写大数据文本挖掘的考查报告,需要用到 jieba切词,于是在pycharm中安装 jieba 库 首先是在 File—settings中通过搜索安装,然而安了五分钟之后还是失败了 于是通过终端输 ...

  9. ASP.NET MVC 数据传递 控制器向视图传递

    控制器向视图传递 MVC 控制器向视图传递传递主要分为单页面传递和全局页面传递 1.单页面传递主要是用 ViewData属性 和ViewBag属性 语法: 赋值: ViewData["名称& ...

  10. (Java实现) 洛谷 P1042 乒乓球

    题目背景 国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及.其中1111分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役.华华就是其中一位,他 ...