@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. HTML中id与name的通俗区别

    转自:https://blog.csdn.net/qq_35038153/article/details/70215356 https://zhidao.baidu.com/question/7582 ...

  2. 腾讯云的ftp搭建

    一开始配置完后 发现用xftp链接登录成功 但是列表无法列举出来 然后又用力cmd.filezilla发现都是一个主动被动问题 pasv_enable=YES.pasv_min_port=60000. ...

  3. 201771010117马兴德 实验二 Java基本程序设计(1)

    实验二 Java基本程序设计(1)  第一部分    理论知识的学习. 第三章Java基本程序设计结构 1  基本知识: (1)标识符:标识符由字母.下划线.美元符号和数字组成,且第一个符号不能为数字 ...

  4. CF894C Marco and GCD Sequence

    题目链接:http://codeforces.com/contest/894/problem/C 题目大意: 按照严格递增的顺序给出 \(m\) 个数作为公因数集,请你构造出一个数列,对于数列中的任意 ...

  5. vue使用stylus样式预处理器

    vue使用stylus样式预处理器,样式总是报错,需要从上一行的样式回车换行才不会报错 <style lang="stylus" scoped> .navbar mar ...

  6. Spring全家桶一一SpringBoot与Mybatis

    Spring全家桶系列一一SpringBoot与Mybatis结合 本文授权"Java知音"独家发布. Mybatis 是一个持久层ORM框架,负责Java与数据库数据交互,也可以 ...

  7. 重学 Java 设计模式:实战抽象工厂模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  8. Java——异常处理,数据库连接

    在学习数据库连接时看到try(){}结构,查了一下写在这里: import java.sql.Connection; import java.sql.DriverManager; import jav ...

  9. Dubbo源码阅读-服务导出

    Dubbo服务导出过程始于Spring容器发布刷新事件,Dubbo在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可分为三个部分,第一部分是前置工作,主要用于检查参数,组装URL.第二部分是导出服 ...

  10. Java IO(二)File

    Java IO(二)File 一.概述 在 Java 中,File 类是 java.io 包中唯一代表磁盘文件本身的对象,也就是说,如果希望在程序中操作文件和目录,则都可以通过 File 类来完成.F ...