首页 > 其他分享 >Codeforces Round 985 div1+2 个人题解(A~E)

Codeforces Round 985 div1+2 个人题解(A~E)

时间:2024-11-13 11:09:01浏览次数:1  
标签:10 int 题解 Codeforces 整数 985 选择 leq 测试用例

Codeforces Round 985 div1+2 个人题解(A~E)

Dashboard - Refact.ai Match 1 (Codeforces Round 985) - Codeforces

火车头

#include <bits/stdc++.h>

using namespace std;

#define ft first
#define sd second

#define yes cout << "yes\n"
#define no cout << "no\n"

#define Yes cout << "Yes\n"
#define No cout << "No\n"

#define YES cout << "YES\n"
#define NO cout << "NO\n"

#define pb push_back
#define eb emplace_back

#define all(x) x.begin(), x.end()
#define all1(x) x.begin() + 1, x.end()
#define unq_all(x) x.erase(unique(all(x)), x.end())
#define unq_all1(x) x.erase(unique(all1(x)), x.end())
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3fLL

#define RED cout << "\033[91m"     // 红色
#define GREEN cout << "\033[92m"   // 绿色
#define YELLOW cout << "\033[93m"  // 蓝色
#define BLUE cout << "\033[94m"    // 品红
#define MAGENTA cout << "\033[95m" // 青色
#define CYAN cout << "\033[96m"    // 青色
#define RESET cout << "\033[0m"    // 重置

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// typedef __int128_t i128;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<string, ll> psl;

typedef tuple<int, int, int> ti3;
typedef tuple<ll, ll, ll> tl3;
typedef tuple<ld, ld, ld> tld3;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<vi> vvi;
typedef vector<vl> vvl;

// std::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());

template <typename T>
inline T read()
{
    T x = 0;
    int y = 1;
    char ch = getchar();
    while (ch > '9' || ch < '0')
    {
        if (ch == '-')
            y = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    return x * y;
}

template <typename T>
inline void write(T x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x >= 10)
    {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}

/*#####################################BEGIN#####################################*/
void solve()
{
}

int main()
{
    ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    // freopen("test.in", "r", stdin);
    // freopen("test.out", "w", stdout);
    int _ = 1;
    std::cin >> _;
    while (_--)
    {
        solve();
    }
    return 0;
}

/*######################################END######################################*/
// 链接:

A. Set

给你一个正整数 \(k\) 和一个由 \(l\) 至 \(r\) (含)的所有整数组成的集合 \(S\)。

您可以执行以下两步运算的任意次数(可能为零):

首先,从集合 \(S\) 中选择一个数字 \(x\),使得 \(S\) 中至少有 \(k\) 个 \(x\) 的倍数(包括 \(x\) 本身);
然后,从 \(S\) 中删除 \(x\) (注意没有删除任何其他内容)。
求可以进行的最大操作数。

输入
每个测试包含多个测试用例。输入的第一行包含一个整数 \(t\) (\(1 \leq t \leq 10^4\))—— 测试用例的数量。测试用例说明如下。

每个测试用例的唯一一行包含三个整数 \(l\)、\(r\) 和 \(k\) (\(1 \leq l \leq r \leq 10^9\),\(1 \leq k \leq r - l + 1\))—— 最小整数 \(S\)、最大整数 \(S\) 和参数 \(k\)。

输出
对于每个测试用例,输出一个整数——可执行的最大操作数。

示例
输入

8
3 9 2
4 9 1
7 9 2
2 10 2
154 220 2
147 294 2
998 24435 3
1 1000000000 2

输出

2
6
0
4
0
1
7148
500000000

提示
在第一个测试用例中,初始时 \(S=\{3,4,5,6,7,8,9\}\)。一个可能的最佳操作序列是:

选择 \(x=4\) 进行第一次操作,因为 \(S\) 中有两个 \(4\) 的倍数:\(4\) 和 \(8\)。\(S\) 变为 \(\{3,5,6,7,8,9\}\);
选择 \(x=3\) 进行第二次操作,因为 \(S\) 中有三个 \(3\) 的倍数:\(3\)、\(6\) 和 \(9\)。\(S\) 变为 \(\{5,6,7,8,9\}\)。

在第二个测试用例中,初始时 \(S=\{4,5,6,7,8,9\}\)。一个可能的最佳操作序列是:

选择 \(x=5\),\(S\) 变为 \(\{4,6,7,8,9\}\);
选择 \(x=6\),\(S\) 变为 \(\{4,7,8,9\}\);
选择 \(x=4\),\(S\) 变为 \(\{7,8,9\}\);
选择 \(x=8\),\(S\) 变为 \(\{7,9\}\);
选择 \(x=7\),\(S\) 变为 \(\{9\}\);
选择 \(x=9\),\(S\) 变为空集。

在第三个测试用例中,初始时 \(S=\{7,8,9\}\)。对于 \(S\) 中的每个 \(x\),无法找到除 \(x\) 本身以外的其他 \(x\) 的倍数。由于 \(k=2\),您无法进行任何操作。

在第四个测试用例中,初始时 \(S=\{2,3,4,5,6,7,8,9,10\}\)。一个可能的最佳操作序列是:

选择 \(x=2\),\(S\) 变为 \(\{3,4,5,6,7,8,9,10\}\);
选择 \(x=4\),\(S\) 变为 \(\{3,5,6,7,8,9,10\}\);
选择 \(x=3\),\(S\) 变为 \(\{5,6,7,8,9,10\}\);
选择 \(x=5\),\(S\) 变为 \(\{6,7,8,9,10\}\)。

解题思路

对于一个数\(n\),我们能构造出的最大的有 \(k\) 个 \(x\) 的倍数的\(x\)为\(\lfloor \frac{n}{k}\rfloor\)。因此,答案为\(\max(0,\lfloor \frac{r}{k}\rfloor-l+1)\)

实现代码

void solve()
{
    ll l, r, k;
    cin >> l >> r >> k;
    cout << max(0ll, r / k - l + 1) << "\n";
}

B. Replacement

您有一个长度为 \(n\) 的二进制字符串 \(s\),而艾瑞丝会给出另一个长度为 \(n-1\) 的二进制字符串 \(r\)。

艾瑞丝将和你玩一个游戏。在游戏过程中,你将对 \(s\) 执行 \(n-1\) 操作。在第 \(i\) 次操作中(\(1 \leq i \leq n-1\)):

首先,你要选择一个索引 \(k\),使得 \(1 \leq k \leq |s| - 1\) 且 \(s_k \neq s_{k+1}\)。如果无法选择这样的索引,那么就输了;
然后,将 \(s_k s_{k+1}\) 替换为 \(r_i\)。请注意,这会使 \(s\) 的长度减少 \(1\)。
如果所有的 \(n-1\) 操作都成功执行,那么你就赢了。

请判断你是否有可能赢得这个游戏。

输入
每个测试包含多个测试用例。输入的第一行包含一个整数 \(t\) (\(1 \leq t \leq 10^4\))—— 测试用例的数量。测试用例说明如下。

每个测试用例的第一行包含一个整数 \(n\) (\(2 \leq n \leq 10^5\))—— \(s\) 的长度。

第二行包含长度为 \(n\) (\(s_i = 0\) 或 \(1\))的二进制字符串 \(s\)。

第三行包含长度为 \(n-1\) (\(r_i = 0\) 或 \(1\))的二进制字符串 \(r\)。

保证所有测试用例中 \(n\) 的总和不超过 \(10^5\)。

输出
对于每个测试用例,如果能赢得游戏,则打印 "YES"(不带引号),否则打印 "NO"(不带引号)。

您可以用任何大小写(大写或小写)输出答案。例如,字符串 "yEs"、"yes"、"Yes" 和 "YES" 将被识别为肯定回答。

示例
输入

6
2
11
0
2
01
1
4
1101
001
6
111110
10000
6
010010
11010
8
10010010
0010010

输出

NO
YES
YES
NO
YES
NO

提示
在第一个测试用例中,您无法执行第一次操作。因此,您输了游戏。

在第二个测试用例中,您可以选择 \(k=1\) 进行唯一的操作,之后 \(s\) 变为 \(1\)。因此,您赢得了游戏。

在第三个测试用例中,您可以执行以下操作:\(110 \to r_1 = 0101 \to r_2 = 010 \to r_3 = 11\)。

解题思路

注意到我们每次是选择一个\(01\)或者\(10\)来进行替换,使其留下\(1\)或者\(0\),因此,每个替换都等价于删除另一种数字,例如替换为\(1\)等价于删除一个\(0\),所以,我们可以维护\(0\)和\(1\)的数量,如果在最后一次删除前\(0\)和\(1\)的数量归零则游戏输了。

实现代码

void solve()
{
    int n;
    string s, r;
    cin >> n >> s >> r;
    int cnt0 = 0;
    int cnt1 = 0;
    for (auto c : s)
    {
        if (c == '1')
            cnt1++;
        else
            cnt0++;
    }
    if (cnt0 == 0 || cnt1 == 0)
    {
        NO;
        return;
    }
    for (int i = 0; i < n - 1; i++)
    {
        if (r[i] == '1')
            cnt0--;
        else
            cnt1--;
        if (i == n - 2)
            continue;
        if (cnt0 == 0 || cnt1 == 0)
        {
            NO;
            return;
        }
    }
    YES;
}

C. New Rating

你好,Codeforcescode!

凯文曾经是 Codeforces 的参与者。最近,KDOI 团队开发了一个名为 Forcescode 的新在线裁判。

凯文参加过 Forcescode 上的 \(n\) 场比赛。在第 \(i\) 场比赛中,他的表现评分为 \(a_i\)。

现在他黑进了 Forcescode 的后台,将选择一个时间间隔 \([l,r]\) (\(1 \leq l \leq r \leq n\)),然后跳过这个时间间隔内的所有比赛。之后,他的评分将按以下方式重新计算:

最初,他的评分为 \(x=0\);
每次 \(1 \leq i \leq n\),在第 \(i\) 场比赛之后:
如果 \(l \leq i \leq r\),则跳过这场比赛,等级分保持不变;
否则,他的评级将根据以下规则更新:
如果 \(a_i > x\),他的评分 \(x\) 将增加 \(1\);
如果 \(a_i = x\),他的评分 \(x\) 将保持不变;
如果 \(a_i < x\),他的评分 \(x\) 将减少 \(1\)。
如果凯文以最佳方式选择了区间 \([l,r]\),您必须帮助他找到重新计算后的最大可能评分。注意凯文至少要跳过一次比赛。

输入
每个测试包含多个测试用例。输入的第一行包含一个整数 \(t\) (\(1 \leq t \leq 5 \cdot 10^4\))—— 测试用例的数量。测试用例说明如下。

每个测试用例的第一行包含一个整数 \(n\) (\(1 \leq n \leq 3 \cdot 10^5\))—— 竞赛次数。

第二行包含 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\) (\(1 \leq a_i \leq n\))—— 竞赛中的性能评级。

保证所有测试用例中 \(n\) 的总和不超过 \(3 \cdot 10^5\)。

输出
对于每个测试用例,输出一个整数——如果凯文以最佳方式选择间隔,重新计算后可能的最大评级。

示例
输入

5
6
1 2 3 4 5 6
7
1 2 1 1 1 3 4
1
1
9
9 9 8 2 4 4 3 5 3
10
1 2 3 4 1 3 2 1 1 10

输出

5
4
0
4
5

提示
在第一个测试用例中,凯文必须跳过至少一场比赛。如果他选择任何长度为 \(1\) 的区间,他的评分在重新计算后将等于 \(5\)。

在第二个测试用例中,凯文的最佳选择是选择区间 \([3,5]\)。在重新计算期间,他的评分变化如下:

\(0 \to a_1=1 \to a_2=2 \to \text{跳过}2 \to \text{跳过}2 \to \text{跳过}2 \to a_6=3 \to a_7=4\)。

在第三个测试用例中,凯文必须跳过唯一的比赛,因此他的评分将保持在初始值 \(0\)。

在第四个测试用例中,凯文的最佳选择是选择区间 \([7,9]\)。在重新计算期间,他的评分变化如下:

\(0 \to a_1=9 \to a_2=9 \to a_3=8 \to a_4=2 \to a_5=4 \to a_6=4 \to \text{跳过}4 \to \text{跳过}4 \to \text{跳过}4\)。

在第五个测试用例中,凯文的最佳选择是选择区间 \([5,9]\)。

解题思路

我们可以设计三个\(dp\)值\(f,g,h\),\(f[i]\)代表第\(i\)次比赛不进行任何跳过的评分,\(g[i]\)代表第\(i\)次比赛正在进行跳过的最大评分,\(h[i]\)代表第\(i\)次比赛已经进行跳过后的最大平方,我们令\(calc(a[i])\)代表评级的更新规则,则可以得到以下状态转移方程:\(f[i]=f[i-1]+clac(a[i]),g[i]=\max(g[i-1],f[i]),h[i]=\max(h[i-1]+calc(a[i]),g[i-1])\)

实现代码

void solve()
{
    int n;
    cin >> n;
    vi a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    vi f(n + 1, -inf);
    vi g(n + 1, -inf);
    vi h(n + 1, -inf);
    f[0] = g[0] = h[0] = f[1] = h[1] = 0;
    for (int i = 1; i <= n; i++)
    {
        int v = a[i];
        if (f[i - 1] < v)
            f[i] = f[i - 1] + 1;
        else if (f[i - 1] == v)
            f[i] = f[i - 1];
        else
            f[i] = f[i - 1] - 1;

        g[i] = max(f[i], g[i - 1]);
        if (i == 1)
            continue;
        if (h[i - 1] < v)
            h[i] = h[i - 1] + 1;
        else if (h[i - 1] == v)
            h[i] = h[i - 1];
        else
            h[i] = h[i - 1] - 1;

        h[i] = max(h[i], g[i - 1]);
    }
    cout << h[n] << endl;
}

D. Cool Graph

给你一个无向图,其中有 \(n\) 个顶点和 \(m\) 条边。

您最多可以执行以下操作 \(2 \cdot \max(n,m)\) 次:

选择三个不同的顶点 \(a\)、\(b\) 和 \(c\),然后对每条边 \((a,b)\)、\((b,c)\) 和 \((c,a)\) 执行以下操作:
如果该边不存在,则添加该边。相反,如果存在,则删除。
当且仅当以下条件之一成立时,图才被称为酷图:

该图没有边,或
该图是一棵树。
您必须通过执行上述操作使图形冷却。请注意,您最多可以进行 \(2 \cdot \max(n,m)\) 次操作。

可以证明,总是存在至少一个解。

输入
每个测试包含多个测试用例。第一行输入包含一个整数 \(t\) (\(1 \leq t \leq 10^4\))—— 测试用例的数量。测试用例说明如下。

每个测试用例的第一行包含两个整数 \(n\) 和 \(m\) (\(3 \leq n \leq 10^5\),\(0 \leq m \leq \min\left(\frac{n(n-1)}{2}, 2 \cdot 10^5\right)\))—— 顶点数和边数。

接着是 \(m\) 行,\(i\) 行包含两个整数 \(u_i\) 和 \(v_i\) (\(1 \leq u_i, v_i \leq n\))—— 第 \(i\) 条边所连接的两个节点。

保证所有测试用例中 \(n\) 的总和不超过 \(10^5\),所有测试用例中 \(m\) 的总和不超过 \(2 \cdot 10^5\)。

保证给定图中不存在自循环或多重边。

输出
对于每个测试用例,在第一行输出一个整数 \(k\) (\(0 \leq k \leq 2 \cdot \max(n,m)\))—— 运算次数。

然后输出 \(k\) 行,第 \(i\) 行包含三个不同的整数 \(a\)、\(b\) 和 \(c\) (\(1 \leq a,b,c \leq n\))—— 你在第 \(i\) 次操作中选择的三个整数。

如果有多个解,可以输出其中任意一个。

示例
输入

5
3 0
3 1
1 2
3 2
1 2
2 3
3 3
1 2
2 3
3 1
6 6
1 2
1 6
4 5
3 4
4 6
3 6

输出

0
1
1 2 3
0
1
1 2 3
3
1 3 6
2 4 5
3 4 6

提示
在第一个测试用例中,图已经是酷图,因为没有边。

在第二个测试用例中,执行唯一的操作后,图变成了一棵树,因此是酷图。

在第三个测试用例中,图已经是酷图,因为它是一棵树。

在第四个测试用例中,执行唯一的操作后,图没有边,因此是酷图。

解题思路

看到限制条件为最多可以进行 \(2 \cdot \max(n,m)\) 次操作,结合树的边数为 \(n-1\) ,因此我们可以考虑先将图删掉尽可能能多的边,然后再重新构建出一棵树,刚好可以接近用完操作。

顺着这个思路往下想,对于一个度数大于等于 \(2\) 的点 \(x\) ,我们可以选择对 \(x\) 和它的两个邻接点 \(y\) 和 \(z\) 进行操作,如果 \(y\) 和 \(z\) 存在一条边,则一次性删除了三条边,否则,我们删除了两条边并构建了一条边 \((y,z)\) ,至少删除了一条边。因此,我们最多不会超过 \(m\) 次,就可以将 这个图删的只剩下孤点和孤边。如果没有孤边,说明所有边已被删除,直接满足要求。

考虑对一堆孤点和孤边进行操作来构建一棵树。

我们可以选取一个孤边作为树的基础。

如果遇见孤点,则对树的两个端点 \(x\) 和 \(y\) 以及孤点 \(z\) 进行操作,这样我们相当于在 \(x\) 和 \(y\) 之间插入了一个点 \(z\) 使得边 \(x\rarr y\) 变成 \(x \rarr z \rarr y\) ,然后我们把 \(z\) 赋值给 \(y\) 即可。

如果遇见孤边,则对孤边的两个端点 \(u\) 和 \(v\) 和树的端点 \(x\) 进行操作,这样我们相当于将 \(u\) 和 \(v\) 与端点 \(x\) 建边,使得边 \(u \rarr v ,x\) 变成 \(u \rarr x \larr v\) 。

实现代码

void solve()
{
    int n, m;
    cin >> n >> m;
    vector<set<int>> adj(n + 1);
    for (int i = 0; i < m; i++)
    {
        int u, v;
        cin >> u >> v;
        adj[u].insert(v);
        adj[v].insert(u);
    }
    if (m == 0)
    {
        cout << "0\n";
        return;
    }
    vector<array<int, 3>> ans;
    auto del = [&](int a, int b, int c)
    {
        adj[a].erase(b);
        adj[b].erase(a);
        adj[a].erase(c);
        adj[c].erase(a);
        if (adj[b].find(c) != adj[b].end())
        {
            adj[b].erase(c);
            adj[c].erase(b);
        }
        else
        {
            adj[b].insert(c);
            adj[c].insert(b);
        }
    };
    for (int i = 1; i <= n; i++)
    {
        while (adj[i].size() >= 2)
        {
            int a = i;
            int b = *adj[i].begin();
            int c = *next(adj[i].begin());
            ans.pb({a, b, c});
            del(a, b, c);
        }
    }
    int u = 0, v = 0;
    for (int i = 1; i <= n; i++)
    {
        if (adj[i].size() == 1)
        {
            u = i;
            v = *adj[i].begin();
            break;
        }
    }
    if (u)
    {
        vb vis(n + 1);
        vis[u] = vis[v] = 1;
        for (int i = 1; i <= n; i++)
        {
            if (vis[i])
                continue;
            if (adj[i].size() == 1)
            {
                ans.pb({u, i, *adj[i].begin()});
                vis[i] = 1;
                vis[*adj[i].begin()] = 1;
            }
            else
            {
                ans.pb({u, v, i});
                vis[i] = 1;
                v = i;
            }
        }
    }
    cout << ans.size() << "\n";
    for (auto [a, b, c] : ans)
    {
        cout << a << " " << b << " " << c << "\n";
    }
}

E. Common Generator

对于两个整数 \(x\) 和 \(y\) (\(x,y \geq 2\)),当且仅当 \(x\) 可以通过执行下面的操作转换为 \(y\) 时,我们才会说 \(x\) 是 \(y\) 的生成器:

选择 \(x\) 的除数 \(d\) (\(d \geq 2\)),然后将 \(x\) 增加 \(d\)。
例如:

\(3\) 是 \(8\) 的生成器,因为我们可以进行以下运算:\(3 \xrightarrow{d=3} 6 \xrightarrow{d=2} 8\);
\(4\) 是 \(10\) 的生成器,因为我们可以进行以下运算:\(4 \xrightarrow{d=4} 8 \xrightarrow{d=2} 10\);
\(5\) 不是 \(6\) 的生成器,因为我们无法通过上述操作将 \(5\) 转化为 \(6\)。

现在,凯文给你一个数组 \(a\),由 \(n\) 个成对不同的整数 (\(a_i \geq 2\)) 组成。

你必须找到一个整数 \(x \geq 2\),使得每个 \(1 \leq i \leq n\) 的生成数 \(x\) 都是 \(a_i\) 的生成数,或者确定这样的整数不存在。

输入
每个测试包含多个测试用例。输入的第一行包含一个整数 \(t\) (\(1 \leq t \leq 10^4\))—— 测试用例的数量。测试用例说明如下。

每个测试用例的第一行都包含一个整数 \(n\) (\(1 \leq n \leq 10^5\))—— 数组 \(a\) 的长度。

第二行包含 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\) (\(2 \leq a_i \leq 4 \cdot 10^5\))—— 数组 \(a\) 中的元素。可以保证这些元素是成对不同的。

保证所有测试用例中 \(n\) 的总和不超过 \(10^5\)。

输出
对于每个测试用例,输出一个整数 \(x\)—— 您找到的整数。如果不存在有效的 \(x\),则打印 \(-1\)。

如果有多个答案,可以输出任意一个。

示例
输入

4
3
8 9 10
4
2 3 4 5
2
147 154
5
3 6 8 25 100000

输出

2
-1
7
3

提示
在第一个测试用例中,对于 \(x=2\):

\(2\) 是 \(8\) 的生成器,因为我们可以进行以下运算:\(2 \xrightarrow{d=2} 4 \xrightarrow{d=4} 8\);
\(2\) 是 \(9\) 的生成器,因为我们可以进行以下运算:\(2 \xrightarrow{d=2} 4 \xrightarrow{d=2} 6 \xrightarrow{d=3} 9\);
\(2\) 是 \(10\) 的生成器,因为我们可以进行以下运算:\(2 \xrightarrow{d=2} 4 \xrightarrow{d=2} 6 \xrightarrow{d=4} 10\)。

在第二个测试用例中,可以证明不可能找到四个整数的公共生成器。

解题思路

由于一个数 \(x\) 可以增加它的因数 \(d\) ,我们很容易就可以想到,要构造一个数 \(a_i\) ,我们只要要构造出它的因数的倍数 \(kd\) 并使得 \(kd \le a_i\),我们就可以很轻松的构造出 \(a_i\) 。由于每次操作都是对当前值进行加法,因此我们因数 \(d\) 选的越小,我们的操作空间越大,所以为了构造出 \(a_i\) ,我们一定是选择它的最小质因数 \(p\) 来进行构造。

  1. 考虑 \(a_i\) 为偶数,我们只要选择 \(x=2\),就一定可以构造出 \(a_i\) 。
  2. 考虑 \(a_i\) 为非质数的奇数,我们也只要选择 \(x=2\),就一定可以构造出 \(a_i\) 。对于\(a_i\),我们只需要将 \(x\) 加上 \(p-1\) 次 \(2\) 就可以获得因数最小包含 \(a_i\) 最小质数因子 \(p\) 的数 \(2\times p\) 。由于\(a_i\) 为非质数的奇数,其最小质因子最小为 \(3\) ,因此 $a_i \gt 2\times p $,我们只要对 \(2 \times p\) 不断加上 \(p\) 就可以得到 \(a_i\) 。
  3. 考虑 \(a_i\) 为质数,我们只能选择它自己来获得它。

综上

  1. 如果 \(a\) 中质数数量大于 \(1\) ,则不存在符合要求的整数。

  2. 如果 \(a\) 中质数数量等于 \(0\) ,则选择 \(x=2\) 一定可以构造出所有 \(a_i\) 。

  3. 如果 \(a\) 中质数数量等于 \(1\) ,则我们只能选择选择 \(x=\text{pri}\) ,\(\text{pri}\) 为唯一的质数。

    考虑检查\(x=\text{pri}\) 是否可以生成所有 \(a_i\)

    • 对于 \(a_i\) 为偶数,只要 \(a_i \le 2\times \text{pri}\) ,我们就可以使得选择器包含因数 \(2\) 从而构造出所有偶数。
    • 对于 \(a_i\) 为奇数,只要\(a_i - p \le 2\times \text{pri}\) ,我们就可以使得选择器包含因数 \(2\) 从而构造出 \(2 \times p\) 进而构造出 \(a_i\) 。

实现代码

const int N = 4e5;

vector<int> minp;   // 存储每个数的最小质因子
vector<int> primes; // 存储找到的所有质数

// 欧拉筛函数
void sieve(int n)
{
    minp.assign(n + 1, 0); // 初始化最小质因子数组
    primes.clear();        // 清空质数数组

    for (int i = 2; i <= n; i++)
    {
        if (minp[i] == 0)
        {                        // 如果 minp[i] 仍为 0,说明 i 是质数
            minp[i] = i;         // 记录 i 的最小质因子为自身
            primes.push_back(i); // 将 i 添加到质数列表中
        }

        // 遍历已找到的质数
        for (auto p : primes)
        {
            if (i * p > n)
            { // 如果 i * p 超过 n,停止
                break;
            }
            minp[i * p] = p; // 记录 i * p 的最小质因子
            if (p == minp[i])
            { // 如果当前质数等于 i 的最小质因子,停止
                break;
            }
        }
    }
}

void solve()
{
    int n;
    cin >> n;
    vi a(n);
    int cntPri = 0;
    int pri = 0;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        if (minp[a[i]] == a[i])
        {
            cntPri++;
            pri = a[i];
        }
    }
    if (cntPri >= 2)
    {
        cout << "-1\n";
        return;
    }
    if (cntPri == 0)
    {
        cout << "2\n";
        return;
    }
    for (int i = 0; i < n; i++)
    {
        if (a[i] == pri)
            continue;
        int v = a[i] & 1 ? a[i] - minp[a[i]] : a[i];
        if (pri * 2 > v)
        {
            cout << "-1\n";
            return;
        }
    }
    cout << pri << "\n";
}

这场没打,第二天就是区赛,不敢打。

感觉这场挺简单的。

标签:10,int,题解,Codeforces,整数,985,选择,leq,测试用例
From: https://www.cnblogs.com/extractstars/p/18543507

相关文章

  • [CF1935E] Distance Learning Courses in MAC 题解
    [CF1935E]DistanceLearningCoursesinMAC难度正常的一道题。首先我们发现“挑选若干个区间”就是一句废话,因为按位或只会贡献答案而不会减小答案。所以我们需要在\([L,R]\)的每个区间都挑一个数,使得最终的按位或最大。想办法让尽可能多的二进制位都变成\(1\),且越是高......
  • Solution - Codeforces 1394B Boboniu Walks on Graph
    考虑先分析最后的图会长成什么样。因为每个点都只会连出一条有向边,且最后还能走回自己。所以可以知道的是图会有许多个环来组成,且每个环都无交。但是这个判定条件明显不是很优秀,考虑继续转化。考虑到对于一个有向环,每个点的出度和入度都需要为\(1\)。那么出度为\(1\)题目......
  • Solution - Codeforces 1217E Sum Queries?
    对于这个“好的”的判定条件看起来有点奇怪,不妨结合上题目要求的“最小\(sum\)”一起考虑。因为要最小化\(s_p\),所以一个比较直观的想法是先从选的数个数入手。考虑到如果选的只有\(1\)个数\(a_i\),那么\(sum=a_i\),一定是好的,排除。如果选的是\(2\)个数\(a_i,a_j\),......
  • [USACO06NOV] Corn Fields G 题解
    题目链接[USACO06NOV]CornFieldsG题解这是一道典型的状压dp,对于\(M\)行\(N\)列的图,由于每个点只有\(1\)和\(0\)两种状态,我们将其压缩为一个长度为\(M\)的数组,数组(\(g\))的每一项\(g_{i}\)表示状态的二进制表示法表示的数(如\(101\)表示为\(5\)),我们预先处......
  • [CEOI2023] A Light Inconvenience 题解
    Description今年CEOI的开幕式上有一场精彩的火炬表演。表演者们站成一排,从\(1\)开始从左往右编号。每个表演者举着一根火炬,初始只有一个举着点燃的火炬的表演者。表演分为\(Q\)幕。在第\(a\)幕开始之前,要么\(p_a>0\)个表演者从右侧加入表演,他们的火炬是熄灭的;要么最......
  • gym103102H AND = OR 题解
    非常巧妙的一个题。我们首先考虑单组询问该怎么做。首先需要注意到一个结论,即设答案为\(x\),那么对于\(\forally<x\),\(y\)都应该放在与组;同样的,对于\(\forally>x\),\(y\)都应该放在与组。进一步的,我们观察在\(\text{popcount}\)上也有同样的性质,即对于\(\forally,......
  • 好题记录 [集训队互测 2023] 优惠购物 题解
    首先发现这个过程的限制比较多,那么考虑重新描述这个过程。令\(x_i\)表示在第\(i\)个物品上使用了\(x_i\)张券,那么一组\(x_{1\simn}\)就描述了一个方案。方便起见,令\(s_i\)为前i个物品买完后剩了几张券,那么有:\(s_0=m\)\(s_i=s_{i-1}+\lfloor\frac{a_i-......
  • 【题解】洛谷P7287: 「EZEC-5」魔法
    P7287「EZEC-5」魔法感觉好题有思维,但是我没认真读题,看到样例就我以为了,他让任意一个区间满足大于\(S\)即可不是全部。我们手搓一下样例就可以发现,对于加法我们不加白不加的话肯定全部的数都加上,乘法肯定要等到加完后才开始,这些都是贪心思路。然后就是开始搭配操作了,我遇到......
  • 题解:「2017 山东一轮集训 Day7」逆序对
    LibreOJ6077前置知识:生成函数、组合数先考虑平方怎么做。\(f_{i,j}\)表示处理了前\(i\)个值,逆序对有\(j\)个。显然可以转移到\(f_{i+1,j},f_{i+1,j+1},f_{i+1,j+2},...,f_{i+1,j+i}\)。然后发现这个东西是个很简单的递推,而且长得很生成函数,于是可以很自然的写成\[1\t......
  • 题解:[SCOI2016] 美味
    前置知识:可持久化线段树(主席树)洛谷3293[SCOI2016]美味问题有一个长度为\(n\)的序列\(a_1,a_2,...,a_n\)。每次询问给你\(b\)、\(x\),你需要求出\(\max\{a_i+x\bigoplusb\}\)。\(1\lel\ler\len\le2\times10^5,0\lea_i,b,x<10^5\)首先,有\(l,r\)应该......