赞
踩
根据给的公式化简后变为gcd(a,b,c)根据算数基本定理,推一下就可以了
然后我们对1到mx的树求约数,并记录约数的次数,我们选择一个最大的且次数大于等3的就是gcd
- int mx;
- vector<int> g[N];
- vector<int> cnt[N];
- int n;
- int a[N];
- void solve()
- {
- cin >> n;
- for (int i = 1; i <= n; i++)
- {
- cin >> a[i];
- mx = max(mx, a[i]);
- }
- for (int i = 1; i <= mx; i++)
- {
- for (int j = 1; j * i <= mx; j++)
- {
- g[i * j].pb(i);
- }
- }
- vector<int> ans;
- sort(a + 1, a + 1 + n);
- for (int i = 1; i <= n; i++)
- {
- int t = a[i];
- for (auto ed : g[t])
- {
- cnt[ed].pb(t);
- }
- }
- int res = 0;
- for (int i = 1; i <= mx; i++)
- if (cnt[i].size() >= 3)
- res = i;
- for (int i = 0; i < 3; i++)
- cout << cnt[res][i] << " ";
- }

赛时写的记录全部区间和,然后sort判断区间是否相交,但是时间复杂度好像有点问题,应该不是很对。
这里看了别人写的
注意1需要特殊处理一下,一开始就不存进set里面
- const int N = 1003;
- int a[N];
- int n;
- int s[N];
- signed main()
- {
- scanf("%d", &n);
- for (int i = 1; i <= n; i++)
- scanf("%d", &a[i]), s[i] = s[i - 1] + a[i];
-
- multiset<int> S;
- for (int l = 1; l <= n; l++) // 提前把1全删去了
- {
- for (int r = l + 1; r <= n; r++)
- {
- S.insert(s[r] - s[l]);
- }
- }
- int res = 1e18;
- for (int r = 1; r < n; r++) // 但是l==1的时候并没有,所以一开始就调过1
- {
- for (int l = 1; l <= r; l++) // 本身也被r==l的时候删去了
- {
- int val = s[r] - s[l - 1];
-
- auto it = S.lower_bound(val);
- if (it != S.end())
- {
- int ans = abs(*it - val);
- res = min(res, ans);
- }
- if (it != S.begin())
- {
- it--;
- int ans = abs(*it - val);
- res = min(res, ans);
- }
- }
- for (int r2 = r + 1; r2 <= n; r2++) // 提前把下一个断点删去
- {
- S.erase(S.find(s[r2] - s[r]));
- }
- }
- printf("%lld\n", res);
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。