CF1684G Euclid Guess

很需要直觉的一个题,想到关键就很简单了

首先注意到允许输出的数对数量很多,完全不用考虑 \(2\times 10^4\) 的限制,那么直觉就是让每个 pair 产生尽可能少的数

首先考虑怎么能只产生一个数,不妨设这个数为 \(x\),则最小的 pair 只能取 \((3x,2x)\),因此 \(\le \frac{m}{3}\) 的数都是能单独产生的

因此很容易想到把数根据和 \(\frac{m}{3}\) 的大小关系分为两种,对于 \(>\frac{m}{3}\) 的数,手玩一下会发现它们不可能同时出现在生成数列中的前两个位置

因此 \(>\frac{m}{3}\) 的数必然需要和若干个 \(\le \frac{m}{3}\) 的匹配才行,但简单手玩发现选超过两个数显然不如直接选头尾两个数来的优

那么问题转化为一个二分图匹配问题,对于 \(a>\frac{m}{3},b\le\frac{m}{3}\),若 \(2a+b\le m\and b\mid a\),则 \(a\)\(b\) 连一条边

最后看所有 \(>\frac{m}{3}\) 的数是否都能匹配即可,多余的 \(\le \frac{m}{3}\) 的数可以自行处理

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=1005;
typedef pair <int,int> pi;
int n,m,a[N],vis[N],from[N]; vector <int> A,B,v[N];
inline bool find(CI now,CI idx)
{
    for (auto to:v[now]) if (vis[to]!=idx)
    {
        vis[to]=idx;
        if (from[to]==-1||find(from[to],idx))
        return from[to]=now,1;
    }
    return 0;
}
signed main()
{
    RI i,j; for (scanf("%lld%lld",&n,&m),i=1;i<=n;++i) scanf("%lld",&a[i]);
    for (i=1;i<=n;++i) if (3*a[i]<=m) B.push_back(a[i]); else A.push_back(a[i]);
    for (i=0;i<A.size();++i) for (j=0;j<B.size();++j)
    {
        int a=A[i],b=B[j];
        if (2*a+b>m||a%b!=0) continue;
        v[i].push_back(j);
    }
    memset(from,-1,sizeof(from));
    int res=0; for (i=0;i<A.size();++i) res+=find(i,i+1);
    if (res!=A.size()) return puts("-1"),0;
    vector <pi> ans;
    for (j=0;j<B.size();++j)
    {
        if (from[j]==-1) { ans.push_back(pi(3*B[j],2*B[j])); continue; }
        int a=A[from[j]],b=B[j]; ans.push_back(pi(2*a+b,a+b));
    }
    printf("%lld\n",(int)ans.size());
    for (auto [x,y]:ans) printf("%lld %lld\n",x,y);
    return 0;
}
posted @ 2024-07-24 19:43  空気力学の詩  阅读(28)  评论(0编辑  收藏  举报