10184602226 edited 3 年,8 月前
#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <string>
#include <functional>
#include <algorithm>
#include <iomanip>
#include <cmath>
#include <string.h>
using namespace std;
using u64 = uint64_t;
const long double PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446;
//****************************模板BEGIN***********************************
class StringUtil {
public:
//用c来分割s,返回分割后的一个个字符串
vector<string> split(string s, char c);
//去除一个字符串前后的空格
string trim(string s);
//把一个字符串转换为字符vector
vector<char> toCharVector(string s);
//把一个字符vector转换为字符串
string vectorToString(vector<char> v);
//专门用来分割空格
vector<string> splitBlank(string s);
};
class BigNumUtil {
public:
//两个超大正整数的加法
string bigDecimalAdd(string num1, string num2);
//两个超大正整数的乘法
string bigDecimalMultiply(string num1, string num2);
//两个超大正整数的减法,注意需要num1≥num2
string bigDecimalMinus(string num1, string num2);
//两个超大正整数的除法,小数部分为零的话就不会显示,如果除不尽,cir_start和cir_end指出了循环节的首尾(小数点后第x位到小数点后第y位)
string bigDecimalDivide(string up, string down, int& cir_start, int& cir_end);
//超大正整数的Cnm(n是大的)
string bigDecimalCnm(int n, int m);
//两个超大正整数比较大小,num1大的话返回1,相同返回0,num1小的话返回-1
int bigDecimalCompare(string num1, string num2);
//把一个小数转换为分数,如果是无限循环小数,循环节需要用[]包起来,返回分数的分子和分母,分别存在up和down中
void floatToFraction(string floatString, long long& up, long long& down);
//把一个数转换为科学计数法,num是正数,p为有效位的位数(不包括小数点)
//返回形式为aFb,超出p的话a会四舍五入,不足p的位数用0补
void numToSci(string num, int p, string& a, string& b);
};
class MathUtil {
public:
//最大(G)公约数
long long getGCD(long long a, long long b);
//最小(L)公倍数
long long getLCM(long long a, long long b);
//计算kBase^kExp
unsigned long long pow(unsigned long long const kBase, unsigned long long const kExp);
//计算Cnm
unsigned long long combine(int n, int m);
//大数情况,计算kBase^kExp再对kMod取余后的结果
unsigned long long powAndMod(unsigned long long const kBase, unsigned long long const kExp, unsigned long long const kMod);
//大数情况,下面三个函数都是为了计算 Cnm%mod 的,用第三个就行
unsigned long long exp_mod(unsigned long long a, unsigned long long b, unsigned long long p);
unsigned long long Comb(unsigned long long a, unsigned long long b, unsigned long long p);
unsigned long long combineAndMod(unsigned long long n, unsigned long long m, unsigned long long mod);
};
//专门用来求解二项式(ax+by)^k中x^n*y^m的系数,通式为Ckn*a^n*b^m
class PolynomialUtil {
public:
//重点就在于把阶乘打表
vector<unsigned long long> factorial;
//这个构造方法最多使用一次,因为打表很花时间
//maxK指的是k的最大值,mod是指结果对多少取余,这两个参数题目一般都会给出,如果maxK不给那就取一个较大的值
PolynomialUtil(int maxK, unsigned long long mod);
unsigned long long go(unsigned long long a, unsigned long long b, unsigned long long k, unsigned long long n, unsigned long long m, unsigned long long mod);
};
//初始化一个m*n的二维数组,使用dft填充,返回的vector可以当作数组一样使用
template<typename T>
vector<vector<T>> initMatrix(int m, int n, T dft);
//****************************模板END*************************************
int currentSum = 0;
int ans = 0;
void backTracking(map<int, int>& vals) {
if (vals.size() == 0) {
ans = max(ans, currentSum);
return;
}
for (auto it = vals.begin(); it != vals.end(); it++) {
int first = (*it).first;
int second = (*it).second;
int second_before;
int second_after;
currentSum += (first * second);
vals.erase(first + 1);
vals.erase(first - 1);
backTracking(vals);
currentSum -= (first * second);
vals[first] = second;
}
}
int main() {
int T;
cin >> T;
for (int t = 0; t < T; t++) {
int amount;
cin >> amount;
map<int, int> vals;
for (int i = 0; i < amount; i++) {
int x;
cin >> x;
if (vals.find(x) == vals.end()) {
vals[x] = 1;
}
else {
vals[x] = vals[x] + 1;
}
}
auto copy = vals;
backTracking(copy);
cout << ans << endl;
currentSum = 0;
ans = 0;
}
}
//****************************模板BEGIN***********************************
vector<string> StringUtil::split(string s, char c) {
vector<string> result;
int len = s.size();
string temp = "";
for (int i = 0; i < len; i++) {
if (s[i] != c) {
temp += s[i];
}
else {
result.push_back(temp);
temp = "";
}
}
if (temp != "") {
result.push_back(temp);
}
return result;
}
string StringUtil::trim(string s) {
string res = "";
int ptr = 0;
while (s[ptr] == ' ') {
ptr++;
}
while (ptr != s.size()) {
res += s[ptr++];
}
auto it = res.end() - 1;
while (*it == ' ') {
res.erase(it);
it--;
}
return res;
}
vector<char> StringUtil::toCharVector(string s) {
vector<char> res;
for (int i = 0; i < s.size(); i++) {
res.push_back(s[i]);
}
return res;
}
string StringUtil::vectorToString(vector<char> v) {
string res = "";
for (char c : v) {
res += c;
}
return res;
}
vector<string> StringUtil::splitBlank(string s) {
vector<string> result;
s = StringUtil().trim(s);
int ptr = 0;
bool processChar = true;
string temp = "";
while (true) {
if (processChar) {
if (s[ptr] != ' ') {
temp += s[ptr];
ptr++;
}
else {
result.push_back(temp);
temp = "";
processChar = false;
}
}
else {
if (s[ptr] != ' ') {
temp += s[ptr];
processChar = true;
}
ptr++;
}
if (ptr == s.size()) {
if (temp != "") {
result.push_back(temp);
}
break;
}
}
return result;
}
string BigNumUtil::bigDecimalAdd(string num1, string num2) {
string s = num2;
string l = num1;
if (num1.size() <= num2.size()) {
s = num1;
l = num2;
}
int ssize = s.size();
int lsize = l.size();
int sptr = ssize - 1;
int lptr = lsize - 1;
vector<int> v;
int up = 0;
while (true) {
int digit1 = s[sptr--] - '0';
int digit2 = l[lptr--] - '0';
int cal = digit1 + digit2 + up;
if (cal >= 10) {
up = 1;
cal -= 10;
}
else {
up = 0;
}
v.push_back(cal);
if (sptr == -1) {
while (lptr != -1) {
cal = l[lptr--] - '0' + up;
if (cal >= 10) {
up = 1;
cal -= 10;
}
else {
up = 0;
}
v.push_back(cal);
}
if (up == 1) {
v.push_back(1);
}
break;
}
}
string res = "";
for (int i = v.size() - 1; i >= 0; i--) {
res += (v[i] + '0');
}
return res;
}
string BigNumUtil::bigDecimalMultiply(string num1, string num2) {
string s = num2;
string l = num1;
if (num1.size() <= num2.size()) {
s = num1;
l = num2;
}
int ssize = s.size();
int lsize = l.size();
vector<string> numList;
for (int i = ssize - 1; i >= 0; i--) {
stack<char> temp;
int digit1 = s[i] - '0';
int up = 0;
for (int j = lsize - 1; j >= 0; j--) {
int digit2 = l[j] - '0';
int cal = digit1 * digit2 + up;
if (cal >= 10) {
up = cal / 10;
cal = cal % 10;
}
else {
up = 0;
}
temp.push(cal + '0');
if (j == 0 && up != 0) {
temp.push(up + '0');
}
}
string res = "";
while (!temp.empty()) {
res += temp.top();
temp.pop();
}
//补上0,比如40*123时,那个0得在这里补上
for (int j = 0; j < ssize - 1 - i; j++) {
res += "0";
}
numList.push_back(res);
}
string res = "0";
for (int i = 0; i < numList.size(); i++) {
res = BigNumUtil::bigDecimalAdd(res, numList[i]);
}
return res;
}
string BigNumUtil::bigDecimalMinus(string num1, string num2) {
if (num1 == num2) {
return "0";
}
int size1 = num1.size();
int size2 = num2.size();
int ptr1 = size1 - 1;
int ptr2 = size2 - 1;
int borrow = 0;
stack<char> stk;
while (true) {
int cal = num1[ptr1--] - '0' - (num2[ptr2--] - '0') - borrow;
if (cal < 0) {
borrow = 1;
cal += 10;
}
else {
borrow = 0;
}
stk.push(cal + '0');
if (ptr2 == -1) {
while (ptr1 != -1) {
int cal = num1[ptr1--] - '0' - borrow;
if (cal < 0) {
borrow = 1;
cal += 10;
}
else {
borrow = 0;
}
stk.push(cal + '0');
}
while (stk.top() == '0') {
stk.pop();
}
break;
}
}
string res = "";
while (!stk.empty()) {
res += stk.top();
stk.pop();
}
return res;
}
string BigNumUtil::bigDecimalDivide(string up, string down, int& cir_start, int& cir_end) {
if (up == "0") {
return "0";
}
if (up == down) {
return "1";
}
//准备好分母的所有倍数,后续可以直接取用
vector<string> timesOfDown;
timesOfDown.push_back("0");
timesOfDown.push_back(down);
for (int i = 2; i <= 10; i++) {
timesOfDown.push_back(bigDecimalMultiply(string(1, i + '0'), down));
}
int ptr = 0;
int upSize = up.size();
//被减数
string currentString = "";
string intPart = "";
//处理整数部分
if (bigDecimalCompare(up, down) == 1) {
while (true) {
if (ptr < upSize) {
currentString += up[ptr];
}
else if (ptr == upSize) {
//如果currentString不为"",说明整数部分除不尽,还有小数部分,现在的这个currentString就是后续处理小数部分时的分子
up = currentString;
break;
}
ptr++;
for (int i = 1; i < 11; i++) {
if (bigDecimalCompare(timesOfDown[i], currentString) == 1) {
//减数
string minu = timesOfDown[i - 1];
//商
intPart += (i - 1 + '0');
//作差
currentString = bigDecimalMinus(currentString, minu);
//余数为0,说明除尽了
if (currentString == "0") {
currentString = "";
}
break;
}
}
}
//去除前导0
auto it = intPart.begin();
while (*it == '0') {
intPart.erase(it);
}
}
if (up == "") {
return intPart;
}
else {
if (intPart == "") {
intPart = "0";
}
//被减数
currentString = up;
string floatPart = "";
//记录已经出现过的余数和第一次出现的位置(小数点后x位)
unordered_map<string, int> left;
int index = 0;
while (true) {
bool canStop = false;
index++;
for (int i = 1; i < 11; i++) {
if (bigDecimalCompare(timesOfDown[i], currentString) == 1) {
//减数
string minu = timesOfDown[i - 1];
//商
floatPart += (i - 1 + '0');
if (index == 1) {
floatPart += ".";
}
//作差
currentString = bigDecimalMinus(currentString, minu);
//如果是第一次出现的余数,加入到set中
if (left.find(currentString) == left.end()) {
left.insert(make_pair(currentString, index));
}
//否则,说明出现了循环节
else {
cir_start = left[currentString];
cir_end = index - 1;
canStop = true;
}
//余数为0,说明除尽了
if (currentString == "0") {
canStop = true;
}
currentString += "0";
break;
}
}
if (canStop) {
break;
}
}
return intPart + floatPart.substr(1);
}
}
int BigNumUtil::bigDecimalCompare(string num1, string num2) {
if (num1.size() > num2.size()) {
return 1;
}
if (num1.size() < num2.size()) {
return -1;
}
int ptr = 0;
while (ptr != num1.size()) {
if (num1[ptr] > num2[ptr]) {
return 1;
}
if (num1[ptr] < num2[ptr]) {
return -1;
}
ptr++;
}
return 0;
}
template<typename T>
vector<vector<T>> initMatrix(int m, int n, T dft) {
vector<vector<T>> matrix;
vector<T> row;
row.resize(n, dft);
matrix.resize(m, row);
return matrix;
}
long long MathUtil::getLCM(long long a, long long b) {
return a * b / getGCD(a, b);
}
long long MathUtil::getGCD(long long a, long long b) {
long long max = (a > b ? a : b);
long long min = (a < b ? a : b);
long long res = max % min;
while (res) {
max = min;
min = res;
res = max % min;
}
return min;
}
unsigned long long MathUtil::powAndMod(unsigned long long const kBase, unsigned long long const kExp, unsigned long long const kMod) {
unsigned long long ret = 1;
for (unsigned long long i = kExp, base = kBase % kMod; i; i >>= 1) {
if (i & 1) {
ret = ret * base % kMod;
}
base = base * base % kMod;
}
return ret;
}
unsigned long long MathUtil::pow(unsigned long long const kBase, unsigned long long const kExp) {
unsigned long long ret = 1;
for (unsigned long long i = kExp, base = kBase; i; i >>= 1) {
if (i & 1) {
ret = ret * base;
}
base = base * base;
}
return ret;
}
unsigned long long MathUtil::exp_mod(unsigned long long a, unsigned long long b, unsigned long long p) {
long long res = 1;
while (b != 0) {
if (b & 1) res = (res * a) % p;
a = (a * a) % p;
b >>= 1;
}
return res;
}
unsigned long long MathUtil::Comb(unsigned long long a, unsigned long long b, unsigned long long p) {
if (a < b) return 0;
if (a == b) return 1;
if (b > a - b) b = a - b;
unsigned long long ans = 1, ca = 1, cb = 1;
for (unsigned long long i = 0; i < b; ++i) {
ca = (ca * (a - i)) % p;
cb = (cb * (b - i)) % p;
}
ans = (ca * exp_mod(cb, p - 2, p)) % p;
return ans;
}
unsigned long long MathUtil::combineAndMod(unsigned long long n, unsigned long long m, unsigned long long mod) {
unsigned long long ans = 1;
while (n && m && ans) {
ans = (ans * Comb(n % mod, m % mod, mod)) % mod;
n /= mod;
m /= mod;
}
return ans;
}
unsigned long long MathUtil::combine(int n, int m) {
if (m < n - m) m = n - m;
unsigned long long ans = 1;
for (int i = m + 1; i <= n; i++) ans *= i;
for (int i = 1; i <= n - m; i++) ans /= i;
return ans;
}
PolynomialUtil::PolynomialUtil(int maxK, unsigned long long mod) {
factorial.resize(maxK + 1);
factorial[0] = 1;
for (int i = 1; i < maxK + 1; ++i) {
factorial[i] = factorial[i - 1] * i % mod;
}
}
unsigned long long PolynomialUtil::go(unsigned long long a, unsigned long long b, unsigned long long k, unsigned long long n, unsigned long long m, unsigned long long mod) {
unsigned long long inv_binom = MathUtil().powAndMod(factorial[n] * factorial[m] % mod, mod - 2, mod);
unsigned long long apow = MathUtil().powAndMod(a, n, mod);
unsigned long long bpow = MathUtil().powAndMod(b, m, mod);
unsigned long long ans = factorial[k] * inv_binom % mod;
ans = ans * apow % mod;
ans = ans * bpow % mod;
return ans;
}
string BigNumUtil::bigDecimalCnm(int n, int m) {
string up = "1";
for (int i = 0; i < m; i++) {
up = BigNumUtil().bigDecimalMultiply(up, to_string(n - i));
}
string down = "1";
for (int i = 2; i <= m; i++) {
down = BigNumUtil().bigDecimalMultiply(down, to_string(i));
}
int useless;
return BigNumUtil().bigDecimalDivide(up, down, useless, useless);
}
/*
无循环小数:直接gcd没啥好说的
纯循环小数:一个循环节有几个数,分母就有几个9,分子则为一个循环节上的数
例 0.3=3/9, 0.347=347/999
混循环小数,循环节有几个数,分母就有几个9,不循环的有几个数,分母再添几个0,分子是从不循环到一个循环节数减去不循环的数
例 0.32=(32-3)/90, 0.2134=(2134-21)/9900
*/
void BigNumUtil::floatToFraction(string s, long long& up, long long& down) {
auto dot = s.find('.');
u64 a = stoull(s.substr(0, dot)), n, m;
auto rec = s.find('[');
if (rec == s.npos) { // 有限小数
n = stoull(s.substr(dot + 1));
m = u64(pow(10, s.length() - dot - 1));
}
else { // 循环小数
s.erase(rec, 1);
n = stoull(s.substr(dot + 1));
if (dot + 1 != rec)n -= stoull(s.substr(dot + 1, rec - dot - 1));
m = u64(pow(10, s.length() - rec - 1)) - 1;
m *= u64(pow(10, rec - dot - 1));
}
auto g = MathUtil().getGCD(n, m);
n /= g;
m /= g;
up = n + m * a;
down = m;
}
void BigNumUtil::numToSci(string s, int p, string& a, string& b) {
int power = 0;
bool isFloat = false;
//有小数点
if (s.find('.') != -1) {
isFloat = true;
//得到整数部分
string intPart = "";
for (char c : s) {
if (c != '.') {
intPart += c;
}
else {
break;
}
}
//整数部分为0
if (intPart == "0") {
power = -1;
int ptr = s.find('.');
while (s[ptr] == '0' || s[ptr] == '.') {
if (s[ptr] == '0') {
power--;
}
ptr++;
}
s = s.substr(ptr);
}
//整数部分大于等于10
else if (BigNumUtil().bigDecimalCompare(intPart, "10") >= 0) {
power = intPart.size() - 1;
s.erase(s.begin() + s.find('.'));
}
//整数部分为1~9
else {
power = 0;
s.erase(s.begin() + 1);
}
}
//以下统一处理全是整数的情况
//四舍五入
if (s.size() > p) {
char toBeIgnored = s[p];
//需要向上进位
if (toBeIgnored >= '5' && toBeIgnored <= '9') {
int carry = 1;
int ptr = p - 1;
while (true) {
s[ptr] = s[ptr] + carry;
if (s[ptr] > '9') {
s[ptr] = '0';
carry = 1;
ptr--;
if (ptr == -1) {
s.insert(s.begin(), '1');
power++;
break;
}
}
else {
break;
}
}
string s2 = s.substr(0, p);
if (p != 1) {
s2.insert(s2.begin() + 1, '.');
}
if (isFloat) {
a = s2;
b = to_string(power);
}
else {
a = s2;
b = to_string(s.size() - 1);
}
}
//不需要进位
else {
string s2 = s.substr(0, p);
if (p != 1) {
s2.insert(s2.begin() + 1, '.');
}
if (isFloat) {
a = s2;
b = to_string(power);
}
else {
a = s2;
b = to_string(s.size() - 1);
}
}
}
else {
int pow = s.size();
while (s.size() <= p) {
s += "0";
}
string s2 = s.substr(0, p);
if (p != 1) {
s2.insert(s2.begin() + 1, '.');
}
if (isFloat) {
a = s2;
b = to_string(power);
}
else {
a = s2;
b = to_string(pow - 1);
}
}
}
//****************************模板END*************************************