250
取叶子节点最大值
500
可以看出A=s1+s2,B=s2+s1,满足这种的都能找到一个合适的C(s1,s2长度可以为0)
所以对于任何一个A,循环移位得到的B都满足,但是循环移位有可能是重复,和循环节有关系,找出n的因子,每个因子的算出来,重复的减去即可。
1000
如果两个数组都没有重复的元素的话,直接FFT即可
FFT是C[i+j] = sum{ A[i] * B[i] }
这题要求的是C[i+j] = sum{ min(A[i], B[i]) }
这题有重复的数据,如果枚举重复次数p,从1枚举到10,if(cnta[i]>=p) A[i]=1; else A[i]=0;
这样只有0,1,就能FFT了。
大于10的,不超过10000个,就可以10000^2暴力搞了。
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <cstring> using namespace std; class SumOfArrays { public: string findbestpair(int, vector<int> , vector<int> ); }; #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> typedef long long type; struct comp { double x, y; comp(double _x = 0, double _y = 0) : x(_x), y(_y) { } }; const int N = 1 << 18; const double pi2 = 3.1415926535897932 * 2; comp a[N], b[N], tmp[N]; int n, bn; type res[N]; inline comp W(int n, bool inv) { double ang = inv ? -pi2 / n : pi2 / n; return comp(cos(ang), sin(ang)); } int bitrev(int x) { int ans = 0; for (int i = 1; i <= bn; ++i) ans <<= 1, ans |= x & 1, x >>= 1; return ans; } void dft(comp *a, bool inv) { int step, to; comp w, wi, A, B; for (int i = 0; i < n; ++i) { to = bitrev(i); if (to > i) std::swap(a[to], a[i]); } for (int i = 1; i <= bn; ++i) { wi = W(1 << i, inv); w = comp(1, 0); step = 1 << (i - 1); for (int k = 0; k < step; ++k) { for (int j = 0; j < n; j += 1 << i) { int t = j | k, d = j | k | step; A = a[t]; B.x = w.x * a[d].x - w.y * a[d].y; B.y = w.x * a[d].y + w.y * a[d].x; a[t].x = A.x + B.x, a[t].y = A.y + B.y; a[d].x = A.x - B.x, a[d].y = A.y - B.y; } comp tmp; tmp.x = w.x * wi.x - w.y * wi.y; tmp.y = w.x * wi.y + w.y * wi.x; w = tmp; } } } int mul(int n1, int *x1, int n2, int *x2) { n = std::max(n1, n2); for (bn = 0; (1 << bn) < n; ++bn) ; ++bn; n = 1 << bn; for (int i = 0; i < n; ++i) a[i] = b[i] = comp(0, 0); for (int i = 0; i < n1; ++i) a[i] = comp(x1[i], 0); for (int i = 0; i < n2; ++i) b[i] = comp(x2[i], 0); dft(a, false); dft(b, false); for (int i = 0; i < n; ++i) { tmp[i].x = a[i].x * b[i].x - a[i].y * b[i].y; tmp[i].y = a[i].x * b[i].y + a[i].y * b[i].x; } dft(tmp, true); for (int i = 0; i < n; ++i) res[i] = (type) (tmp[i].x / n + 0.1); for (--n; n && !res[n]; --n) ; return n + 1; } int A[100005], B[100005]; int nn; void getdata(int A[], int a0, int a1, int a2, int a3, int a4, int a5) { A[0] = a0; A[1] = a1; for (int i = 2; i < nn; ++i) A[i] = ((long long) A[i - 1] * (long long) a2 + (long long) A[i - 2] * (long long) a3 + (long long) a4) % (long long) a5; } int aa[200005], bb[200005], ca[200005], cb[200005]; long long ans[12][N]; long long hahaha[N]; vector<pair<int, long long> > va, vb; string SumOfArrays::findbestpair(int NN, vector<int> Aseed, vector<int> Bseed) { int i, j, k, p; nn = NN; getdata(A, Aseed[0], Aseed[1], Aseed[2], Aseed[3], Aseed[4], Aseed[5]); getdata(B, Bseed[0], Bseed[1], Bseed[2], Bseed[3], Bseed[4], Bseed[5]); memset(ca, 0, sizeof(ca)); memset(cb, 0, sizeof(cb)); for (i = 0; i < nn; ++i) { ca[A[i]]++; cb[B[i]]++; } memset(ans, 0, sizeof(ans)); for (p = 1; p <= 10; ++p) { memset(aa, 0, sizeof(aa)); memset(bb, 0, sizeof(bb)); for (i = 0; i < (1 << 17); ++i) { if (ca[i] >= p) aa[i] = 1; if (cb[i] >= p) bb[i] = 1; } mul(1 << 17, aa, 1 << 17, bb); for (i = 0; i < N; ++i) ans[p][i] = res[i]; } for (p = 1; p < 10; ++p) { for (i = 0; i < N; ++i) ans[p][i] -= ans[p + 1][i]; } p = 11; va.clear(); vb.clear(); for (i = 0; i < 100000; ++i) { if (ca[i] > 10) va.push_back(make_pair(i, ca[i])); if (cb[i] > 10) vb.push_back(make_pair(i, cb[i])); } memset(hahaha, 0, sizeof(hahaha)); for (i = 0; i < va.size(); ++i) { for (j = 0; j < vb.size(); ++j) { if (va[i].second >= vb[j].second) { hahaha[va[i].first + vb[j].first] += vb[j].second; ans[10][va[i].first + vb[j].first]--; } else { hahaha[va[i].first + vb[j].first] += va[i].second; ans[10][va[i].first + vb[j].first]--; } } } for (p = 1; p <= 10; ++p) { for (i = 0; i < N; ++i) { hahaha[i] += ans[p][i] * p; } } int best = 0; for (i = 0; i < N; ++i) { if (hahaha[i] >= hahaha[best]) best = i; } char ret[100]; sprintf(ret, "%lld %d", hahaha[best], best); return ret; }