Codeforces Round 1042 (Div. 3) H. Sea, You & copriMe 题解
Codeforces Round 1042 (Div. 3)
给定数组,求四元组使得前两个互质且后两个互质,互不相同且不要求升序排列(可以交错)
可以转化为图论问题,将互质的两个数连边,题意为找到图上大小为 2 的一组匹配。
考虑这个图的性质。
若出现两个出度 \(\ge 2\) 的点显然可行,这两个点分别匹配就行。
贪心的考虑我们会先将出度为 2 的点与其邻居中出度最小的点匹配,因为这样减少了浪费。
若只剩下出度为 \(1\) 的点显然随便。
匹配完后再从图中将这两个点删除,再次匹配,得到答案。
一个 \(x\) 点的出度为
\[\sum_{i=1}^{n} [gcd(a_i,a_x)=1]
\]
若为 \(a_x = 1\) 还需减去自身。
根据莫比乌斯反演,
\[\sum_{i=1}^{n} \sum_{d|a_i,d|a_x} \mu(d)
\]
\[\sum_{d|a_x} \mu(d) \times cnt_d
\]
\(cnt_d\) 为是 \(d\) 倍数的数的个数。
可以快速计算。
至于匹配,暴力扫一遍即可。
时间复杂度 \(O(n\times d(m))\) 。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define PII pair<int,int>
#define rep(k,a,b) for (int k = a;k <= b;k++)
#define adde(a,b) v[a].push_back(b)
#define addev(a,b,c) v[a].push_back({b,c});
#define rd read
#define all(a) a.begin(),a.end()
#define mem(a,b) memset(a,b,sizeof a);
#define pb push_back
#define vct vector
#define rev(T) reverse(T.begin(),T.end())
#define endl "\n"
const int N = 2e5+5,M =1e6+5;
int mu[M],primes[M],cnt;
vct<int> yin[M];
void shai(int n)
{
vct<int> vis(n + 2);
cnt = 0;
mu[1] = 1;
for (int i = 2;i <= n;i++)
{
if (!vis[i]) primes[cnt++] = i,mu[i] = -1;
for (int j = 0;primes[j] <= n/i;j++)
{
vis[primes[j] * i] = 1;
if (i % primes[j] == 0)
{
mu[primes[j] * i] = 0;
break;
}else mu[primes[j] * i] = mu[i] * -1;
}
}
}
void solvemain()
{
int n,m;cin >> n >> m;
vector<int> a(n + 2),cnt(m + 2),box(m + 2),deg(n + 2);
rep(i,1,n) cin >> a[i],box[a[i]]++;
rep(d,1,m)
{
for (int i = d;i <= m;i+=d) cnt[d] += box[i];
}
vct<int> ans(5);
int maxn = 0,id = -1;
for (int i = 1;i <= n;i++)
{
int res= 0;
for (auto d : yin[a[i]]) res += mu[d] * cnt[d];
if (res > maxn) maxn = res,id = i;
deg[i] = res - (a[i] == 1);
// cout << i << ' '<< deg[i] << endl;
}
ans[1] = id;
int mnid = -1;
for (int i = 1;i <= n;i++)
{
if (i == id) continue;
if (gcd(a[i],a[id]) == 1)
{
if (mnid == -1 || deg[mnid] > deg[i]) mnid = i;
}
}
ans[2] = mnid;
// cout << ans[1] << ' '<< ans[2] << endl;
// ans[2] = i;
int x = mnid;
rep(i,1,m) box[i] = cnt[i] = 0;
rep(i,1,n)
if (i!=x && i!= id) box[a[i]]++;
rep(d,1,m)
{
for (int i = d;i <= m;i+=d) cnt[d] += box[i];
}
rep(i,1,n)
{
if (i == id || i == x) continue;
int res= 0;
for (auto d : yin[a[i]]) res += mu[d] * cnt[d];
if (res)
{
rep(j,1,n)
{
if (j == id || j == x || j == i) continue;
if (__gcd(a[i],a[j]) == 1)
{
cout << ans[1] << ' '<< ans[2] << ' '<< i << ' ' << j << endl;return;
}
}
}
}
cout << 0 << endl;
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(nullptr);
int t;t = 1;cin >> t;
int m = 1e6 ;
for (int i = 1;i <= m;i++)
{
// if (mu[i] != 0)
for (int j = i;j <= m;j+=i)
yin[j].pb(i);
}
shai(m);
while(t--){solvemain();}return 0;
}

浙公网安备 33010602011771号