2023杭电多校4

2023杭电多校4

C - Simple Set Problem

Given kk non empty multiple sets, each multiple set only contains integers with absolute values not exceeding 109109.

It is required to select exactly one number from each multiple set to form an array (a1,a2,…,ak)(a1,a2,…,ak) with a length of kk.

Assuming d=max(a1,a2,…,ak)−min(a1,a2,…,ak)d=max(a1,a2,…,ak)−min(a1,a2,…,ak).Please calculate the minimum dd.

Input

Each test contains multiple test cases.The first line of input contains a single integer t(1≤t≤106)t(1≤t≤106)—the number of test cases.The description of test cases follows.

The first line of each test case contains a single integer k(1≤k≤106)k(1≤k≤106) —— the number of multiple sets.

The following kk lines of each test case first read in a parameter cici —— indicating the size of the ii-th multiple set, followed by cici integers with absolute values not exceeding 109109 —— indicating the elements of the ii-th multiple set.

Guarantee that ∑ki=1ci∑i=1kci for each test case does not exceed 106106, the sum of ∑ki=1ci∑i=1kci for all test cases does not exceed 4×1064×106.

Output

For each testcase, output an integer representing the answer, which is the minimum dd.

Sample

InputcopyOutputcopy
3 2 1 6 3 -7 7 10 4 9 -5 -9 2 8 5 4 3 3 8 2 10 8 1 -7 3 1 6 10 1 1 91 15 0

题目描述:

一共T组输入,每组输入有K个集合,从K个集合中选取K个数,也就是每个集合选取一个数,问这些数字中的最大值减去这些数字中的最小值的最小的值。

解题思路:

利用双指针,对于每一个右端点,存一段至少包含所有集合的点各一个的区间,然后就可以用区间极差来算整体的极差。这道题目非常恶心,非常卡时间,需要用快读和快写来优化一下,另外记得提交到GCC的编译器。
为了找到从每个集合中选择一个数,使得最大值与最小值的差值最小,我们可以使用如下的策略:

  1. 排序与双指针法:将所有集合的元素按照数值大小排序,同时保存元素所属的集合编号。这样,我们可以方便地使用双指针法找到包含至少一个来自每个集合的最小区间,并计算最大值和最小值之间的差值。
  2. 区间维护:我们维护一个窗口,该窗口至少包含所有集合的一个元素。在遍历过程中,如果当前窗口已经包含所有集合的元素,我们尝试缩小窗口的左边界,直到窗口无法再缩小。同时记录当前区间内最大值与最小值的差,并更新全局最优解。
  3. 时间复杂度优化:由于问题规模巨大,需要特别关注输入输出的效率,使用快速输入输出(如 getchar()putchar())来避免常规的 cincout 带来的性能瓶颈。同时要注意算法的复杂度为 O(T×∑i=1kci)O(T \times \sum_{i=1}^{k} c_i)O(T×∑i=1kci),通过使用排序和双指针来确保其高效性。
#include <iostream>
#include <vector>
#include <array>
#include <set>
#include <algorithm>
#include <climits>
#include <iostream>
#include <cstdio>
using namespace std;
#define endl '\n'
inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = x * 10 + ch - '0', ch = getchar();
    return x * f;
}
void write(int x)
{
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
    return;
}
void solved()
{
    int n = read();
    vector<array<int, 2>> arr;
    int ans = 2e9;
    for (int i = 1; i <= n; i++)
    {
        int k = read();
        while (k--)
        {
            int v = read();
            arr.push_back({v,i});
        }
    }
    sort(arr.begin(), arr.end());
    vector<int> vis(n + 1, 0);
    int nums = 0;
    int j = 0;
    for (int i = 0; i < arr.size(); i++)
    {
        array<int, 2> now = arr[i];
        if (!vis[now[1]]++)
        {
            ++nums;
        }
        if (nums == n)
        {
            while (vis[arr[j][1]] > 1)
            {
                --vis[arr[j++][1]];
            }
            ans = min(ans, (arr[i][0] - arr[j][0]));
        }
    }
    write(ans);
    printf("\n");
}
int main()
{
    int T = read();
    while (T--)
    {
        solved();
    }
    return 0;
}

G - Guess

Recently, Stump felt ∑nk=1μ2(k)=∑nk=1μ(k)⌊nk2⌋∑k=1nμ2(k)=∑k=1nμ(k)⌊nk2⌋with his heart immediately, which shocked Yoshinow2001 for a whole year!!
μμis μ(n)μ(n) nncontain square factor (i.e. there are positive integers a2|na2|n) then the. Otherwise, might as well set decomposition of prime factors of n=p1⋅p2⋯⋅pkn=p1⋅p2⋯⋅pk μ(n)=(−1)kμ(n)=(−1)k μ(1)=1,μ(2)=μ(3)=−1μ(1)=1,μ(2)=μ(3)=−1
Recall that nnwith base.

\\You need to calculate:\\

eS(n)mod998244353eS(n)mod998244353

Input

The first line of input is a positive integer T(1≤T≤2000)T(1≤T≤2000) representing the number of data cases.

The next line has a total of TT integers, each of which corresponds to nn as described in the problem, where 1≤n≤10181≤n≤1018.

Output

For each testcase, output an integer representing the answer mod 998244353mod 998244353, separated by a space.

Sample

InputcopyOutputcopy
3 1 2 31 2 3

题目描述:

给定两个式子,一个是U(x),如果x有平方因子,那么他就是0,如果他有k个质因子,那么他就是(-1)^k,要求我们计算一个S(n)=∑d|nμ(nd)ln(d)。

解题思路:

这是一道打表找规律的题目,并且需要一点板子。首先从打表中找出规律,如果输入的数是一个质数的k次,那么答案就是这个质数,其中k大于等于1,如果这个数是1的话当然就是1。那么快速判断一个超级大的数字是否为质数呢,我们就需要套一个板子的代码,这就是米勒-拉宾素性检验(MillerRabbin)算法,然后如果这个数不是质数,因为他最大是1e18,我们无法预处理出这么多的质数,至少要下降到1e6,所以要先判断一下开根号的结果是不是满足题意。

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 1e6 + 10;
const int mod = 998244353;
int isPrime[N];
vector<int> prime;

int Quick_Multiply(int a, int b, int c)
{
    long long ans = 0, res = a;
    while (b)
    {
        if (b & 1)
            ans = (ans + res) % c;
        res = (res + res) % c;
        b >>= 1;
    }
    return (int)ans;
}

int Quick_Power(int a, int b, int c)
{
    int ans = 1, res = a;
    while (b)
    {
        if (b & 1)
            ans = Quick_Multiply(ans, res, c);
        res = Quick_Multiply(res, res, c);
        b >>= 1;
    }
    return ans;
}

bool Miller_Rabin(int x)
{
    if (x == 2)
        return true;
    if (x < 2 || !(x & 1))
        return false;

    int s = 0, t = x - 1;
    while (!(t & 1))
    {
        s++;
        t >>= 1;
    }

    for (int i = 0; i < 10 && prime[i] < x; ++i)
    {
        int a = prime[i];
        int b = Quick_Power(a, t, x);
        for (int j = 1; j <= s; ++j)
        {
            int k = Quick_Multiply(b, b, x);
            if (k == 1 && b != 1 && b != x - 1)
                return false;
            b = k;
        }
        if (b != 1)
            return false;
    }
    return true;
}

void sieve()
{
    for (int i = 2; i < N; i++)
    {
        isPrime[i] = 1;
    }
    for (int i = 2; i < N; i++)
    {
        if (isPrime[i])
        {
            prime.push_back(i);
        }
        for (int &it : prime)
        {
            if (i * it >= N)
            {
                break;
            }
            isPrime[i * it] = 0;
            if (i % it == 0)
            {
                break;
            }
        }
    }
}

bool isPerfectSquare(int v)
{
    int k = sqrt(v);
    return (k * k == v);
}

signed main()
{
    close;
    int T;
    cin >> T;
    sieve();

    for (int i = 1; i <= T; i++)
    {
        if (i > 1)
        {
            cout << " ";
        }
        int v;
        cin >> v;
        if (Miller_Rabin(v) || v == 1)
        {
            cout << v % mod;
            continue;
        }
        if (isPerfectSquare(v) && Miller_Rabin((int)sqrt(v)))
        {
            cout << (int)sqrt(v) % mod;
            continue;
        }

        int flag = 0;
        int originalV = v;
        for (auto j : prime)
        {
            if (j * j > v)
                break;
            while (v % j == 0)
            {
                v /= j;
            }
            if (v == 1)
            {
                cout << j % mod;
                flag = 1;
                break;
            }
            v = originalV;
        }
        if (!flag)
        {
            cout << 1;
        }
    }
    cout << endl;
}

J - Kong Ming Qi

According to legend, Kongming Chess is an intellectual game invented by Kongming during the Three Kingdoms period. In this problem, we make a slight modification to Kongming Chess. The game is played on an (n+2)×(m+2)(n+2)×(m+2) chessboard, and there is one chess piece on each of the n×mn×m positions in the middle of the chessboard.

The rules of Kongming Chess are as follows: Each time, you can choose one chess piece and then choose one of the four directions: up, down, left, or right. Move the chess piece one grid away in the chosen direction from its original position. In addition to the above requirement, the following conditions must be satisfied: There must be a chess piece on the intermediate position between the original position and the target position, and the target position must not have a chess piece. All positions must be on the chessboard.

After the move, the chess piece on the intermediate position is taken away. After each move, one chess piece will be removed from the chessboard. Now, we need you to solve a problem: Given n and m, what is the minimum number of chess pieces left on the chessboard?

Input

The first line contains a positive integer, TT, where 1≤T≤1001≤T≤100, representing the number of query sets.

Next, there will be T lines, each representing a query. Each line contains two positive integers, nn and mm, where 1≤n,m≤651≤n,m≤65.

Output

For each test case, output one line containing an integer representing the answer.

Sample

InputcopyOutputcopy
2 1 2 2 3 1 2

HDU - 7321

题目描述:

一个(n+2)(m+2)的棋盘上有(n)*(m)个棋子,棋子可以跳跃另外一个棋子,当且仅当他们相邻,且该棋子跳跃到的地方没有棋子,问最后棋盘上最少有几颗棋子。

解题思路:

这题需要模拟很多种情况,模拟完就做出来了。

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
signed main()
{
    close;
    int T;
    cin >> T;
    for (int i = 1; i <= T; i++)
    {
        int n, m;
        cin >> n >> m;
        if (n == 1 || m == 1)
        {
            int k = max(n, m);
            cout << k - k / 2 << endl;
            continue;
        }
        if (n % 3 == 0 || m % 3 == 0)
        {
            cout << 2 << endl;
            continue;
        }
        cout << 1 << endl;
    }
}

L - a-b Problem

Alice and Bob are playing a little game. There are nn stones. Alice and Bob take turns picking stones, with Alice going first. Each person can only pick one stone at a time until all the stones are gone. Each stone has two attributes, AiAi and BiBi. When Alice picks a stone, she earns AiAi points, and when Bob picks a stone, he earns BiBi points. The total score for each person is the sum of the points they earn when picking a stone. Both players want to maximize the difference between their scores, aiming to have their own score minus the opponent’s score as large as possible. The question is, what is the final result of Alice’s score minus Bob’s score?

Input

The first line contains a positive integer, TT, representing the number of test cases, where 1≤T≤201≤T≤20.

Next, for each test case, the following format is repeated:

The first line contains a positive integer, nn, where 1≤n≤1051≤n≤105.
The next nn lines contain two integers, AiAi and BiBi, representing the two attributes of the ith stone. The values of AiAi and BiBi satisfy 0≤Ai,Bi≤1090≤Ai,Bi≤109.

Output

For each test case, output one line containing an integer representing the answer.

Sample

InputcopyOutputcopy
2 3 0 2 1 2 3 3 3 1 0 2 3 0 41 -1

HDU - 7323

题目描述:

有T组输入,每组输入有n个对,每个值由a和b组成,A要最大化A,B要最大化B,问最后SUMA-SUMB的值是多少。

解题思路:

直接求一个a+b,然后对他进行排序,从高到低拿即可。

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 1e5 + 10;
struct ss
{
    int sum;
    int a;
    int b;
};
ss input[N];
signed main()
{
    close;
    int T;
    cin >> T;
    for (int i = 1; i <= T; i++)
    {
        int n;
        cin >> n;
        for (int j = 1; j <= n; j++)
        {
            cin >> input[j].a >> input[j].b;
            input[j].sum = input[j].a + input[j].b;
        }
        sort(input + 1, input + 1 + n, [&](const ss &left, const ss &right)
             { return left.sum > right.sum; });
        int sumA = 0;
        int sumB = 0;
        for (int j = 1; j <= n; j++)
        {
            if (j & 1)
            {
                sumA += input[j].a;
            }
            else
            {
                sumB += input[j].b;
            }
        }
        cout << sumA - sumB << endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值