2020河南省第二届CCPC真题解析(附榜单)

A:班委竞选

时间限制: 1 Sec 内存限制: 128 MB

题目:

某班级中有 n 位学生,学号为 1,2,…,n。现在班级中正在举行 m 个班干部职位的竞选,职位用 1,2,…,m 编号。学号为 i 的同学竞选的职位为 ci,获得 ti 票。最终每个职位选择票数最高的同学上任,若存在多个同学票数一致,则选择学号最小的同学上任。
现在给你唱票结果,请你告诉班主任最终的班干部名单。

输入
第一行包含两个整数 n, m (1≤n≤51, 1≤m≤12, m≤n),含义见题目描述。
接下来 n 行,第 i 行包含两个整数 ci, ti (1≤ci≤m, 1≤ti≤n),含义见题目描述。
数据保证每个职位至少有一位同学参与竞选。

输出
输出一行,包含 m 个整数。第 i 个整数表示担任第 i 个班干部职位的同学学号。

样例输入 Copy
5 2
1 2
2 1
2 1
1 1
2 2
样例输出 Copy
1 5
提示
样例输入二
12 8
8 12
6 8
2 6
1 8
1 7
2 9
3 12
4 9
5 1
6 12
7 6
8 8
样例输出二
4 6 7 8 9 10 11 1

第一个样例中,第 1 个岗位有学号 1 和学号 4 两个同学竞选,获得的票数分别为 2 和 1,第 1 个岗位由获得票数最多的学号 1 同学来担任;第 2 个岗位有学号 2, 3 和 5 三个同学竞选,获得的票数分别为 1, 1 和 2,第 2 个岗位由获得票数最多的学号 5 同学来担任。

分析:

原文链接.

AC代码:

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 5e5 + 10;
 
struct node
{
    
    
    int p, id;
    bool operator < (const node &oth)const
    {
    
    
        if (p != oth.p)
            return p > oth.p;
        return id < oth.id;
    }
};
int main()
{
    
    
#ifdef LOCAL
    freopen("E:/input.txt", "r", stdin);
#endif
    map<int, set<node>>mp;
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
    
    
        int c, t;
        cin >> c >> t;
        mp[c].insert({
    
     t, i });
    }
    for (int i = 1; i <= m; i++)
        cout << mp[i].begin()->id << (i == m ? '\n' : ' ');
    return 0;
}

B:广告投放

题目:

时间限制: 3 Sec 内存限制: 512 MB

题目描述
现在有一档综艺节目即将在网络上播出,总共会有 n 集,节目会按顺序逐集播出。节目组决定在某些集节目中投放广告。
节目最初播出时,会有 m 名观众观看。若第 i 集投放有广告,记此时还剩有 c 名观众观看,则会产生 c⋅pi 的收益;但播出后则会让观众的人数变为c′=⌊c/di⌋,即第 i+1 集只会剩有 c′ 名观众观看。如果在第 i 集没有投放广告,则不会产生收益,观众人数也不会变化。
请你帮助节目组计算一下各种可能的方案中,最大的收益和。

输入
第一行,两个整数 n 和 m (1≤n,m≤105),表示节目集数和首播时的观众数量。
第二行,共 n 个整数 pi (1≤pi≤106),表示第 i 集投放广告时每名观众能带来的收益。
第三行,共 n 个整数 di (1≤di≤m),表示第 i 集投放广告后,观众数量会变为人数除以 di 并向下取整。

输出
一个整数,表示可能的最大的收益和。

样例输入 Copy
5 20
9 14 10 4 5
2 7 1 8 10

样例输出 Copy
335

提示
样例输入二
6 5
5 31 53 58 74 97 5 5 4 5 5 4
样例输出二
485

第一个样例中,可以考虑在第 1, 2, 3, 5 集投放广告。这样,在第 1 集时有 2 名观众,投放广告获得收益 2;在第 2 集时有⌊20/2⌋=10 名观众,投放广告获得收益 10×14=140;在第 3 集时有 ⌊10/7⌋=1 名观众,投放广告获得收益 1×10=10;在第 4 集时有 ⌊1/1⌋=1 名观众,但因为没有投放广告,所以没有收益;在第 5 集时有 1 名观众,投放广告获得收益 1×5=5。最终,总收益为 1。这是能够取到最大的收益和的一个方案。
第二个样例中,可以考虑只在第 6 集投放广告,能获得的总收益为 5×97=485,这是能够取到最大的收益和的一个方案。 换个方案,如果选择在第 5, 6 集投放广告,能获得的总收益为 5×74+⌊5/5⌋×97=467,并不如只在第 6 集投放广告获得的总收益高。

分析:

原文链接.

AC代码:

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
 
int p[N], d[N];
ll f[N * 10];
ll g[N * 10];
int vis[N * 10];
int val[N];
int main()
{
    
    
#ifdef LOCAL
    freopen("E:/input.txt", "r", stdin);
#endif
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        scanf("%d", &p[i]);
    for (int i = 1; i <= n; i++)
        scanf("%d", &d[i]);
    int cnt = 0;
    vis[m] = 1;
    val[++cnt] = m;
    for (int i = m; i >= 1; i--)
    {
    
    
        if (vis[i])
        {
    
    
            for (int j = 1; j <= i; j++)
                vis[i / j] = 1;
            val[++cnt] = i;
        }
    }
    for (int i = 1; i <= n; i++)
    {
    
    
        for (int j = 1; j <= cnt; j++)
            f[val[j] / d[i]] = max(f[val[j] / d[i]], g[val[j]] + 1LL * val[j] * p[i]);
        for (int j = 1; j <= cnt; j++)
            g[val[j]] = f[val[j]];
    }
    ll ans = 0;
    for (int i = 0; i <= m; i++)
        ans = max(ans, f[i]);
    cout << ans << endl;
    return 0;
}

C:我得重新集结部队

题目:

时间限制: 1 Sec 内存限制: 128 MB

题目描述
为了保护科普卢星区的和平,大主教阿塔尼斯每时每刻都在指挥部队抗击肆虐的虫群。最近,阿塔尼斯把目光投向了又一颗布满虫群的星球。在这次行动中,阿塔尼斯计划使用狂热者铲除星球上的虫群威胁。
狂热者是星灵的基本近战兵种,每个狂热者有一个攻击力 atk 和一个攻击范围 r。在狂热者发动攻击时,他会冲向距离最近的异虫,在这只异虫处释放 3 次威力强大的旋风斩。若有多只距离最近的异虫,他会选择最早出现的那只。若当前没有存活的异虫,那么这只狂热者会在原地释放旋风斩。每次旋风斩会对所有与攻击者距离小于等于 r 的异虫进行攻击,对每只异虫造成 atk 的伤害(生命值减少 atk)。
当然,这些异虫也是不好惹的。每只异虫具有初始生命值 h,当生命值小于等于 0 时,该异虫将会死亡(并离开战场)。但是,在一次攻击中,若一只异虫受到 3 次旋风斩后仍未死亡,那么它将会对进攻的狂热者进行反击,使这个狂热者不得不离开战场。
在整个战役中,按照时间顺序依次发生了 n 个事件,事件有以下两种:
异虫出现。一只初始生命值为 h 的异虫单位出现在 (x,y)坐标。
折跃狂热者。一个狂热者被折跃到了 (x,y) 坐标,冲向距离最近的异虫(若存在)并发动 3 次旋风斩。若此后该狂热者没有受到反击,那么他将会一直留在战场,但是不会继续进行攻击。
你作为阿塔尼斯的副官,想知道战场的最终情况:每个狂热者是否离开了战场,以及每只异虫是否死亡。

输入
第一行包含一个整数 n (1≤n≤2×103),代表事件的数量。
接下来 n 行,每行给出一种事件,格式为以下两种之一:
1 x y h,代表一个生命值为 h 的异虫出现在了坐标 (x,y)。
2 x y atk r,代表一个攻击力为 atk,攻击半径为 r 的狂热者被折跃到了坐标 (x,y),并立即进行攻击。
上述所有的x,y,r 均为整数,满足 0≤∣x∣,∣y∣,r≤108;所有的 atk,h 均为整数,满足 1≤atk,h≤108。

输出
输出 n 行,第 i 行表示第 i 个事件中出现的异虫或狂热者最终是否留在战场。Yes 表示异虫未死亡或狂热者未离开战场,No 表示异虫死亡或狂热者离开战场,大小写不敏感。

样例输入 Copy
5
1 0 0 4
1 0 1 8
2 1 0 1 1
2 1 0 1 1
2 1 0 1 1

样例输出 Copy
No
No
No
No
Yes

提示
在样例中,发生了如下事件:
事件 1 中,在 (0,0)处出现了一只异虫,其生命值为 4。
事件 2 中,在 (0,1)处新出现了一只异虫,其生命值为 8。
事件 3 中,在 (1,0) 处折跃一只攻击力为 1,攻击半径为 1 的狂热者,他移动到坐标 (0,0) 后,发动 3 次旋风斩。异虫 1,2 分别剩余生命值 1,5,随后狂热者受到反击离开战场。
事件 4 中,在 (1,0) 处折跃一只攻击力为 1,攻击半径为 1 的狂热者,他移动到坐标 (0,0) 后,发动 3 次旋风斩。异虫 1 死亡,异虫 2 剩余生命值 2,随后狂热者受到反击离开战场。
事件 5 中,在 (1,0) 处折跃一只攻击力为 1,攻击半径为 1 的狂热者,他移动到坐标 (0,1) 后,发动 3 次旋风斩。异虫 2 死亡,狂热者留在战场。
因而,最终所有异虫死亡,只有狂热者 5 留在战场。

分析:

原文链接.

AC代码:

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10;
const int mod = 1e9 + 7;
typedef long long ll;
 
struct node
{
    
    
    int x, y;
    ll r;
    bool death;
}insect[N];
int type[N];
ll dis(int a, int b, int c, int d)
{
    
    
    return 1LL * (a - c) * (a - c) + 1LL * (b - d) * (b - d);
}
int main()
{
    
    
#ifdef LOCAL
    freopen("E:/input.txt", "r", stdin);
#endif
    int n;
    int cnt = 0, tot = 0;
    cin >> n;
    while (n--)
    {
    
    
        ++cnt;
        int op;
        scanf("%d", &op);
        if (op == 1)
            scanf("%d%d%lld", &insect[cnt].x, &insect[cnt].y, &insect[cnt].r), type[cnt] = 1;
        else
        {
    
    
            type[cnt] = 2;
            int x, y, atk, r;
            scanf("%d%d%d%d", &x, &y, &atk, &r);
            int k = 0;
            ll d = 1e18;
            for (int i = 1; i <= cnt; i++)
            {
    
    
                if (type[i] == 1 && insect[i].r > 0)
                {
    
    
                    if (d > dis(x, y, insect[i].x, insect[i].y))
                        d = dis(x, y, insect[i].x, insect[i].y), k = i;
                }
            }
            for (int i = 1; i <= cnt; i++)
            {
    
    
                if (!insect[i].death && type[i] == 1 && 1LL * (insect[i].x - insect[k].x) * (insect[i].x - insect[k].x) + 1LL * (insect[i].y - insect[k].y) * (insect[i].y - insect[k].y) <= 1LL * r * r)
                {
    
    
                    insect[i].r -= 3LL * atk;
                    if (insect[i].r <= 0)
                        insect[i].death = 1;
                    else
                        insect[cnt].death = 1;
                }
            }
        }
    }
    for (int i = 1; i <= cnt; i++)
        puts(!insect[i].death ? "Yes" : "No");
    return 0;
}

D:园艺大师

题目:

时间限制: 1 Sec 内存限制: 128 MB

题目描述
小钾立志成为传说中的园艺大师,因此开始练习修剪技术。
园林中有 n 株灌木排成一排,且它们的高度都为一个正整数 h。对于每株灌木,小钾可以进行一次修剪,使其高度变成一个小于 h 的任意正整数;或是不进行修剪,使其高度仍为 h。为了保持灌木丛整体的美观,小钾还提出了 n−1 个要求,第 i 个要求为下列的一种:
第 i 株灌木的高度严格小于第 i+1 株
第 i 株灌木的高度严格大于第 i+1 株
我们称两种修剪方案不同,当且仅当存在某株灌木的最终高度在两种方案中不同。当小钾将所有不同的修剪方案都完成时,他就能提升为园艺大师。但是他实在太忙了,因此请你帮他计算所有不同的修剪方案数量对质数109+7 取模后的值。

输入
第一行包含两个整数 n, h (2≤n≤3×103, 1≤h≤106),含义见题目描述。
第二行包含一个长度为 n−1 的字符串,仅由字符 “<” 与 “>”(不包括引号)组成,表示小钾的要求。若第 i 个字符为 “<”,则要求为"第 i 株灌木的高度严格小于第 i+1 株";若第 i 个字符为 “>”,则要求为"第 i 株灌木的高度严格大于第 i+1 株"。

输出
输出一行一个整数,表示所有不同的修剪方案数量对质数 109+7 取模后的值。

样例输入 Copy
3 3
<>

样例输出 Copy
5

提示
样例输入二
5 12
<>><
样例输出二
16522

第一个样例中,一共有 5 种符合要求的方案:(1,2,1), (1,3,1), (1,3,2), (2,3,1), (2,3,2)。

分析:

AC代码:

E:发通知

题目:

时间限制: 5 Sec 内存限制: 512 MB

题目描述
学院一共有 n 位学生,用 1 编号。每天,学院都会派遣辅导员给学生发送若干通知,以保证各项措施、活动消息得到落实。
现在,学院要求辅导员发送一条关于光盘行动的通知。对于通知信息,同学们的反应往往各不相同,辅导员预测出第 i 号学生收到通知后会产生 wi 的愉悦度。此外,辅导员还观察到第 i 号学生会在 [ai,bi]时间段内实时查阅通知消息,能够收到这段时间内的所有通知;而其他时间将无法收到通知(愉悦度为 0)。
辅导员会选择在某一时刻发布一次通知消息,他希望在至少有 k 名同学收到通知的前提下,使得同学们的总体愉悦度最大。同学们的总体愉悦度是所有同学愉悦度的异或和。请聪明的你帮助辅导员计算最大的总体愉悦度。

输入
第一行包含两个整数 n, k (1≤n≤5×105,1≤k≤n),含义见题目描述。
接下来 n 行,每行包含三个整数 ai, bi, wi (1≤ai≤bi≤109, 0≤wi≤109),含义见题目描述。

输出
输出一行一个整数,即最大的总体愉悦度。若不可能有至少 k 名同学收到通知,输出 −1。

样例输入 Copy
5 1
1 5 8
3 6 2
7 8 4
8 9 0
10 10 1

样例输出 Copy
10

提示
样例输入二
2 2 3 5 8 1 2 4
样例输出二
-1

第一个样例中,辅导员可以选择在时刻 3 发送通知,这样第 1 位和第 2 位同学会收到通知,总体愉悦度可取到最大值,为8⊕2=10。当然,最大的合法方案不止这一种,也可以选择在时刻 5 发送通知,总体愉悦度为 1。
第二个样例中,无论选取哪一时刻发布通知,都无法让两位同学均接收消息,故输出 −。

分析:

原文链接.

AC代码:

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 5e5 + 10;
 
int d[N * 2];
int e[N * 2];
int a[N], b[N], c[N];
int main()
{
    
    
#ifdef LOCAL
    freopen("E:/input.txt", "r", stdin);
#endif
    int n, k;
    cin >> n >> k;
    vector<int>v;
    for (int i = 1; i <= n; i++)
    {
    
    
        scanf("%d%d%d", &a[i], &b[i], &c[i]);
        v.push_back(a[i]), v.push_back(b[i] + 1);
    }
    sort(v.begin(), v.end());
    int cnt = v.erase(unique(v.begin(), v.end()), v.end()) - v.begin();
    for (int i = 1; i <= n; i++)
    {
    
    
        int bg = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
        int ed = lower_bound(v.begin(), v.end(), b[i] + 1) - v.begin() + 1;
        d[bg] ^= c[i], d[ed] ^= c[i];
        e[bg]++, e[ed]--;
    }
    int ans = -1;
    for (int i = 1; i <= cnt; i++)
    {
    
    
        d[i] ^= d[i - 1];
        e[i] += e[i - 1];
        if (e[i] >= k)
            ans = max(ans, d[i]);
    }
    cout << ans << endl;
    return 0;
}

F:旅游胜地

题目:

时间限制: 8 Sec 内存限制: 512 MB

题目描述
有一旅游胜地,可以看做是一个 n 个点、m 条边的连通无向图。每个点都有一个点权,编号为 i 的点的点权为 ai,表示这个点的景观值。
开发商为了能获取收益,准备选择一些点建设商业区,但是会让这些点的景观值大打折扣。具体地说,如果选择编号为 i 的点建设商业区,则会让该点的景观值变为 bi,其中 bi≤ai。
不过对于游客来讲,只要游览相邻的两个点时,景观值的差距不要太大就好。即确定好需要建设商业区的点后,记编号为 i 的点最终的点权为 wi,只要所有边 u,v 的 ∣wu−wv∣ 中最大值尽可能小即可。或者说,最小化有边相连的景观值差距的最大值。
请你帮助开发商计算所有可能的方案中,景观值最大差距的最小值。

输入
第一行,两个正整数 n,m(2≤n≤105, n−1≤m≤min(n(n−1)/2,105) ),表示图的点数和边数。
第二行,共 n 个正整数 ai (1≤ai≤109),表示编号为 i 的点不建设商业区的景观值。
第三行,共 n 个正整数 bi (1≤bi≤109, bi≤ai),表示编号为 i 的点建设商业区后的景观值。
接下来 m 行,每行两个正整数 u,v,表示 u 和 v 有一条边相连。
数据保证图是连通的,也保证没有重边或自环。

输出
一个整数,景观值最大差距的最小值。

样例输入 Copy
4 3
10 7 5 5
6 2 1 2
2 4
3 2
2 1

样例输出 Copy
2

提示
样例输入二
6 6
8 8 7 6 9 9
7 4 6 3 4 7
3 1
4 3
5 1
2 4
1 6
4 1
样例输出二
2

下面两图分别为两个样例的一个方案。点的标记为"编号:景观值",白色填充为没有建立商业区的点,灰色填充的为建立了商业区的点;边权为所连接的两个点的景观值差距。
第一个图中,只有点 1 建立了商业区,景观值最大差距为 2;第二个图中,点 1、2、3、6 建立了商业区,景观值最大差距为 2。
在这里插入图片描述

分析:

AC代码:

G:vvvvvvvim

题目:

时间限制: 3 Sec 内存限制: 512 MB

题目描述
一天,心血来潮的 Toxel 对 vim 进行了魔改。他在 vim 中添加了指令 vvvvvvv,该指令可以在一段文本中选取任意一条连续的路径进行操作。Toxel 将这一全新的文本编辑器命名为 vvvvvvvim。
vvvvvvvim 中的一段文本包含若干行,每行包含若干个从行首开头的字符,与一般的文本编辑器相同。第 i 行左起的第 j 个字符用坐标 (i,j) 表示(i,j 均从 1 开始)。
vvvvvvv 指令选取的连续路径可定义为从文本中某个存在的字符开始,每次向上、下、左、右移动一个字符,通过有限次移动得到的字符序列。移动的过程中不允许走到不存在字符的位置,但可以重复访问同一位置的字符。
形式化地说,vvvvvvv 指令选取的路径可表示为 (x1,y1)→(x2,y2)→⋯→(xt,yt)(t≥1),其中 t 表示路径长度。设 n 表示文本行数,那么要求对于所有的 i(1≤i≤t) 满足 1≤xi≤n,1≤yi≤lenxi。并且对于所有的 i(1≤i<t) 满足 ∣xi−xi+1∣+∣yi−yi+1∣=1。
为了测试你对 vvvvvvvim 的掌握情况,Toxel 给了你两段文本,它们的行数相同,所有对应行的长度也相同。你需要在第一段文本上使用 vvvvvvvim 指令选取一条路径,将路径上所有字符统一修改成字符 ch(ch 可任选),使得两段文本相同。请判断是否可行。两段文本相同是指行数相同,每行的长度相同,且所有对应位置的字符也相同。

输入
注意:本题包含多组测试数据。
第一行包含一个整数 T (1≤T≤5×105),表示数据组数。接下来依次给出 T 组测试数据。
每组测试数据的第一行包含一个整数 n,表示两段文本的行数均为 n (1≤n≤5×105)。
接下来 n 行描述第一段文本的内容。输入的第 i 行包含一个字符串 c1t1c2t2⋯cdtd,表示文本的第 i 行有 d 段,依次为 t1 个 c1,t2 个 c2,以此类推。字符与数字间没有空格,参见样例。保证所有 cj 均为小写字母,tj 为整数且 1≤tj≤109,1≤d≤5×105,∑j=1dtj≤109。
接下来 n 行描述第二段文本的内容,格式和限制与第一段文本相同。保证两段文本所有对应行的长度相同。
保证单个测试点中所有测试数据第一段文本的 d 之和不超过 5×105,第二段文本的 d 之和不超过 5×105。

输出
对于每组测试数据,输出一行一个字符串,Yes 表示可以修改第一段文本使得两段文本相同,No 表示不能,大小写不敏感。

样例输入 Copy
1
2
a2
a1b1
b2
b2

样例输出 Copy
Yes
提示

样例输入二
1
1
a1b1a1
b1a1a1

样例输出二
No

第一个样例中,第一段文本为:
aa
ab
第二段文本为:
bb
bb
可以选择从第一行的第二个字符开始,走到第一行的第一个字符,再走到第二行的第一个字符。将路径选中的这些字符全部修改为字符 b 后,两段文本就相同了。
第二个样例则没有办法只使用一次操作来完成目标。

分析:

AC代码:

H:林克与翻转排列

题目:

时间限制: 1 Sec 内存限制: 128 MB

题目描述
林克穿过果彭加沼泽,来到了壶洞窟的门口。但是一道机关挡住了他的去路,机关上的铭牌刻着:“只有解开迷题的人,方可进入洞窟探寻宝物。”
这个迷题是这样的:机关上有上下两串数字,它们分别是 1∼n 的排列。上方的数字串可以操作,而下方的不行。每次操作可以选取连续的 k 个数字,将它们翻转过来。由于机关有一定的使用寿命,操作至多可以进行 2×105 次,允许不进行任何操作。只有两个序列变得完全相同,门才会开启。
形式化地说,有两个 1∼n的排列a1,a2,⋯,an 和 b1,b2,⋯,bn,每次操作可以选取一个 l,满足 1≤l≤n−k+1,并将子串 al,al+1,⋯,al+k−1 翻转过来。操作之后,a1,a2,⋯,an 会变成 a1,⋯,al−1,al+k−1,⋯,al+1,al,al+k,⋯,an。你需要用若干次操作使得 a1=b1,a2=b2,⋯,an=bn。
请你帮助林克破解这道机关。

输入
第一行包含两个整数 n, k (2≤k≤n≤100, k 为偶数),含义见题目描述。
第二行包含 n 个整数,第 i 个为 ai (1≤ai≤n),表示上方数字串的第 i 个数字。保证所有的 ai 两两不同。
第三行包含 n 个整数,第 i 个为 bi (1≤bi≤n),表示下方数字串的第 i 个数字。保证所有的 bi 两两不同。

输出
如果这道机关无解,输出一行一个整数 −1。
否则输出一种操作的方案。方案第一行,包含一个整数 c,表示操作的次数。c 应当满足 0≤c≤2×105。
接下来 c 行,第 i 行包含一个整数 li,表示第 i 步操作翻转了 ali,ali+1,⋯,ali+k−1 这个子串。li 应当满足1≤li≤n−k+1。
如果有多种方案,输出任意一种即可。可以证明,只要有解,必然存在一种不超过 2×105 次操作的方案。

样例输入 Copy
4 2
1 4 2 3
1 2 3 4

样例输出 Copy
2
2
3
提示
样例输入二
6 4 2 5 4 1 6 3 1 2 3 4 5 6
样例输出二
2
第一个样例,a 的变化为 1,4,2,3→1,2,4,3→1,2,3,4。
第二个样例无解。

分析:

AC代码:

I:太阳轰炸

题目:

时间限制: 2 Sec 内存限制: 128 MB

题目描述
背景:阿塔尼斯,达拉姆的大主教,在艾尔又一次沦陷之后指挥着星灵的最后一艘方舟舰:亚顿之矛。作为艾尔星灵数千年来的智慧结晶,亚顿之矛除了搭载了以太阳能碎片为核心的兵工厂之外,还配备了诸如汇聚射线、太阳能射线枪等威力强大的支援武器。而在这些武器中,最负盛名、也最让敌人胆寒的就是太阳轰炸。
太阳轰炸是一件威力巨大的对星球武器。在太阳轰炸开火时,亚顿之矛将聚集太阳能核心中的太阳能量,向目标坐标发射成百上千枚火焰飞弹。虽然这些火焰飞弹精准度较差,但太阳轰炸的高攻击频率仍然可以让地面上的敌人无法躲避,化为灰烬。
在这一次的行动中,阿塔尼斯的目标是一枚臭名昭著的虚空碎片。在俯视视角下,虚空碎片的投影是一个半径为 R1 的圆,太阳轰炸的攻击散布范围是一个半径为 R2 的圆。这两个圆的圆心均为原点 (0,0)。太阳轰炸将射出 n 枚火焰飞弹,每一枚火焰飞弹等概率地落在攻击散布范围内每一个点上,所有火焰飞弹的落点相互独立。火焰飞弹的伤害范围是以落点为圆心,半径为 r 的圆。若火焰飞弹的伤害范围和虚空碎片的投影相交,则该枚火焰飞弹命中虚空碎片,造成 a 点伤害。若总伤害大于等于 h,则虚空碎片会被摧毁。
摧毁这枚虚空碎片对阿塔尼斯的战略部署非常重要,因此阿塔尼斯想要知道一次太阳轰炸能够摧毁这枚虚空碎片的概率。你需要输出答案对质数 109+7 取模的值。

输入
仅一行,包含六个整数 n, R1, R2, r, a, h (1≤n≤5×106, 1≤R1,R2,r≤108, 1≤a,h≤108),含义见题目描述。

输出
一个整数,表示答案。

样例输入 Copy
3 2 4 1 1 1
样例输出 Copy
636962896
提示
答案对质数109+7 取模的定义:设 M=109+7,可以证明答案可表示为一个既约分数 p/q,其中 , 均为整数且 q 模 M 不余 0。输出满足 0≤x<M 且x⋅q≡p(mod M) 的整数 x。
在这里插入图片描述
上图对应了样例中 R1=2,R2=4,r=1 的情况。其中红色的圆是虚空碎片的投影,蓝色的圆是太阳轰炸的攻击范围。A,B,C 是三个可能的落点,其中 A,C 命中虚空碎片,而 B 没有命中虚空碎片。

分析:

原文链接.

AC代码:

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 5e6 + 10;
 
ll fpow(ll a, int b, int mod) {
    
     ll res = 1; for (; b > 0; b >>= 1) {
    
     if (b & 1) res = res * a % mod; a = a * a % mod; } return res; }
int jc[N], inv[N];
int fz1[N], fz2[N];
int main()
{
    
    
#ifdef LOCAL
    freopen("E:/input.txt", "r", stdin);
#endif
    jc[0] = 1;
    for (int i = 1; i <= 5e6; i++)
        jc[i] = 1LL * jc[i - 1] * i % mod;
    inv[5000000] = fpow(jc[5000000], mod - 2, mod);
    for (int i = 5e6 - 1; i >= 0; i--)
        inv[i] = 1LL * inv[i + 1] * (i + 1) % mod;
    ll n, r1, r2, r, a, h;
    cin >> n >> r1 >> r2 >> r >> a >> h;
    ll fm = 1, x1 = r2 * r2 % mod, x2 = (r1 + r) * (r1 + r) % mod, x3 = (x1 - x2 + mod) % mod;
    fz1[0] = fz2[0] = 1;
    for (int i = 1; i <= n; i++)
    {
    
    
        fm = fm * x1 % mod;
        fz1[i] = 1LL * fz1[i - 1] * x2 % mod;
        fz2[i] = 1LL * fz2[i - 1] * x3 % mod;
    }
    ll res = 0;
    int flag = 0;
    for (int i = 1; i <= n; i++)
    {
    
    
        if (i * a >= h)
        {
    
    
            flag = 1;
            ll f = 1LL * jc[n] * inv[i] % mod * inv[n - i] % mod;
            res = (res + 1LL * f * fz1[i] % mod * fz2[n - i] % mod) % mod;
        }
    }
    if ((r1 + r) >= r2)
    {
    
    
        printf("%d\n", flag);
        exit(0);
    }
    cout << res * fpow(fm, mod - 2, mod) % mod << endl;
    return 0;
}

J:二进制与、平方和

题目:

时间限制: 3 Sec 内存限制: 512 MB

题目描述
请你维护一个长度为 n 的非负整数序列 a1,a2,…,an,支持以下两种操作:
第一种操作会将序列 al,al+1,…,ar 中的每个元素,修改为各自和 x 的"二进制与"(Bitwise binary AND)的值,其中 l,r,x 在每次操作时会给定;
第二种操作会询问序列 al,al+1,…,ar 中所有元素的平方和模 998244353的值,即 ∑i=lrai2 模 998244353,其中 l,r在每次操作时会给定。
总共有 q 次操作,请你在维护序列的过程中,输出第二种操作所询问的答案。注意需要取模。

输入
第一行,一个整数 n (1≤n≤3×105),表示序列的长度。
第二行,共 n 个整数 ai (0≤ai<224),表示序列。
第三行,一个整数 q (1≤q≤3×105),表示询问的数量。
接下来 q 行,每行表示一个操作,输入有两种格式:
第一种操作的格式为 “1 l r x”,表示将序列中编号在区间 [l,r] 的所有元素,修改为和 x 二进制与操作后的值,其中 1≤l≤r≤n, 0≤x<224;
第二种操作的格式为 “2 l r”,表示询问序列中编号在区间 [l,r] 的所有元素的平方和,模 998244353 的值,其中 1≤l≤r≤n。
数据保证至少有一个第二种操作,即保证至少询问一次答案。

输出
每当遇到第二种操作时,输出询问的答案。注意需要取模。

样例输入 Copy
3
13 31 28
4
2 1 3
1 3 3 25
1 1 2 18
2 2 3

样例输出 Copy
1914
900

提示
样例输入二
5
9 11 12 5 1
7
2 1 3
1 3 3 0
1 1 3 9
1 4 5 13
2 1 3
1 4 5 14
2 1 5

样例输出二
346
162
178

样例输入三
4
16777215 16777215 16777215 16777214
4
2 2 2
1 1 4 16777214
2 1 4
2 3 4

样例输出三
981185168
795789897
897017125

“二进制与”(Bitwise binary AND)结果的第 i 个二进制位为 1,当且仅当两个操作数的第 i 位都为 1。

分析:

AC代码:

K:子串翻转回文串

题目:

时间限制: 2 Sec 内存限制: 128 MB

题目描述
给一个串 s=s1s2⋯sn,你可以选定其一个非空子串,然后将该子串翻转。具体来说,若选定的子串区间为 [l,r](1≤l≤r≤n),则翻转后该串变为 s1s2⋯sl−1srsr−1⋯slsr+1⋯sn。
请你回答仅通过一次上述操作后,s 是否能变成回文串。串 s 是回文串,当且仅当它从左至右读出与从右至左读出完全相同,即 s1s2⋯sn=snsn−1⋯s1

输入
注意:本题包含多组测试数据。
第一行包含一个整数 T(1≤T≤5×105),表示数据组数。
接下来的 T 行,每行包含一个仅由英文小写字母组成的字符串 s,含义见题目描述,且串长 ∣s∣ 满足1≤∣s∣≤5×105。
保证字符串总长 ∑∣s∣不超过 5×105。

输出
对于每组测试数据,输出一行一个字符串,若仅通过一次操作后 s 能变成回文串,则输出 Yes,否则输出 No,大小写不敏感。
样例输入 Copy
4
abba
bacad
abacbaa
aabadcdca
样例输出 Copy
Yes
No
Yes
Yes
提示
第一组数据中,abba 翻转带下划线的子串得到回文串 abba。
第二组数据中,无论如何翻转子串,都不能得到回文串。
第三组数据中, abacbaa翻转带下划线的子串得到回文串 aabcbaa。
第四组数据中, aabadcdca翻转带下划线的子串得到回文串 acdabadca。

分析:

原文链接.

AC代码:

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int mod = 20000311;
const int INF = 0x3f3f3f3f;
const int N = 5e5 + 10;
 
struct StringHash 
{
    
    
    ll h[N], w[N], base, mod; 
    void Init(ll b, ll m)
    {
    
    
        h[0] = 0, w[0] = 1, base = b, mod = m;
    }
    void Add(char* s)
    {
    
    
        int len = strlen(s + 1);
        for (int i = 1; i <= len; i++)
            h[i] = (h[i - 1] * base + s[i]) % mod, w[i] = w[i - 1] * base % mod;
    }
    ll Get(int l, int r)
    {
    
    
        return (h[r] - h[l - 1] * w[r - l + 1] % mod + mod) % mod;
    }
}ha1, ha2;
char t[N];
char s[N];
int n;
bool check()
{
    
    
    for (int i = 1; i <= n; i++)
    {
    
    
        if (i <= n - i)
        {
    
    
            if (ha1.Get(1, i) == ha1.Get(n - i + 1, n))
            {
    
    
                if (ha1.Get(i + 1, n - i) == ha2.Get(i + 1, n - i))
                    return 1;
            }
        }
        else
        {
    
    
            int len = n - i;
            if (ha1.Get(n - 2 * len + 1, n - len) == ha1.Get(n - len + 1, n))
            {
    
    
                if (ha1.Get(1, n - 2 * len) == ha2.Get(2 * len + 1, n))
                    return 1;
            }
        }
    }
    return 0;
}
int main()
{
    
    
#ifdef LOCAL
    freopen("E:/input.txt", "r", stdin);
#endif
    ha1.Init(233, 1e9 + 9);
    ha2.Init(233, 1e9 + 9);
    int T;
    cin >> T;
    while (T--)
    {
    
    
        scanf("%s", t + 1);
        int len = strlen(t + 1);
        n = 0;
        for (int i = 1; i <= len; i++)
        {
    
    
            if (t[i] != t[len - i + 1])
            {
    
    
                for (int j = i; j <= len - i + 1; j++)
                    s[++n] = t[j];
                break;
            }
        }
        if (n == 0)
        {
    
    
            puts("Yes");
            continue;
        }
        ha1.Add(s);
        reverse(s + 1, s + n + 1);
        ha2.Add(s);
        int ans = check();
        if (!ans)
        {
    
    
            ha1.Add(s);
            reverse(s + 1, s + n + 1);
            ha2.Add(s);
            ans = check();
        }
        puts(ans ? "Yes" : "No");
    }
    return 0;
}

L:送外卖

题目:

时间限制: 8 Sec 内存限制: 512 MB

题目描述
在智慧岛上,程序员小 Q 每天下班都会在 n 栋公寓之间兼职送外卖。这 n 栋公寓由 m 条双向道路连通,任意两栋公寓可通过这些道路相互到达。第 i 条道路连接公寓 ui,vi,长度为 wi 米。
精通解梦的小 Q 早已在昨夜梦中知晓今日的所有订单信息:今晚,每栋公寓都恰好订了一份外卖,公寓 i 在 qi 秒下单。小 Q 下班后会从 1 公寓骑上他的小电驴,从 0 秒开始送餐。小 Q 可以以不超过 1 m/s的速度沿道路移动,也可以在任意位置休息不动,到达公寓后的送餐时间可以忽略不计。当然,小 Q 不能在下单前将外卖送达,以免引起客户的恐慌。
对于一笔订单,小Q在订单发起后的不同时间送达将会产生不同收益。形式化地说,对一笔订单 j,外卖平台会规定 d 个送达时间节点 qj<t1<t2<⋯<td(单位:秒),以及 d+1 个根据时间变化的收益p1, p2, ⋯, pd+1。注意,收益不一定随着送达时间推迟而减少。设小 Q 在 T 秒送达外卖,那么他的收益为

聪明的你能告诉小 Q,今晚送完所有订单最多能挣多少钱吗?

输入
第一行包含两个整数 n, m (1≤n≤14, n−1≤m≤(n(n−1))/2),分别表示公寓的数量和道路的数量。
接下来 m 行,第 i 行包含三个整数 ui,vi,wi (1≤ui,vi≤n, ui≠vi, 1≤wi≤300),表示第 i 条道路连接公寓 ui,vi,长度为 wi 米。保证无重边。
接下来一行包含 n 个整数,第 i 个整数为 qi (0≤qi≤200),表示第 i 栋公寓订单的发起时刻。
接下来 3n 行,每 3 行依次描述公寓 1,2,⋯,n 订单的收益信息。第一行包含一个整数 d (1≤d≤200)。第二行包含 d 个整数,第 i 个整数为 ti (1≤ti≤200)。第三行包含 d+1 个整数,第 d+1 个整数为 pi (0≤pi≤108)。d,ti,pi的含义见题目描述。
输出
输出一行一个整数,表示最大收益。
样例输入 Copy
3 2
1 2 1
2 3 1
1 3 3
1
2
5 1
1
4
5 4
1
4
5 1
样例输出 Copy
14
提示
样例中,小 Q 在第 0 秒时已经在 1 号公寓等候订单;第 1 秒小 Q 完成 1 号订单(不计时间),获得 5 收益,随后动身前往 3 号公寓,并于第 3 秒抵达;第 3 秒小 Q 完成 3 号订单,获得 5 收益,随后动身前往 2 号公寓,并于第 4 秒抵达;第 4 秒小 Q 完成 2 号订单,获得 4 收益,此时全部订单完成,小 Q 获得最大收益 14。

分析:

AC代码:

欢迎大佬一起进群交流在这里插入图片描述

在这里插入图片描述

榜单:

明天更新!
https://acm.sdut.edu.cn/srk_ccpc/
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43652327/article/details/109907443