链接:to
A . Appeal to the Audience
您是即将举行的Bordfite Arena竞赛比赛的总监。您已经邀请了一堆球员,现在正在为淘汰赛设置比赛,这将确定获胜者。如您所知,BordfiteArena是一款奖励技能的游戏,很少涉及运气。这意味着无论何时有任意数量的玩家玩ordfite竞技场的游戏,最熟练的玩家将永远获胜!因此已经知道了比赛的获胜者,您对此有些担心,您将如何安抚观众?
您进行了简短的调查,以找出观众觉得有趣的地方。没有惊喜:当人们看到熟练的选手竞争时,人们会发现它最有趣。每当比赛进行时,观众从比赛中获得的快乐就是球员技能水平的总和。观众从比赛中获得的总幸福感是所有比赛中获得的幸福感的总和。这是非常有用的信息,因为您当然希望观众在比赛结束时尽可能的开心。
此外,您花了一些时间来问人们他们喜欢哪种淘汰赛形式。事实证明,与其使用普通的旧二叉树作为淘汰日程,他们更喜欢一棵看起来很奇怪的根树,因此您决定使用它。这意味着您要完成的最后一步是将玩家划分到给定树的叶子上,以便在整个锦标赛中最大程度地提高观众的满意度。
样例输入
5 3
5 4 3
0
0
1
1
样例输出
17
求出每个叶节点一共要加多少次 从小到大排 再和给的数组从小到大 匹配求乘积的和
这里用dfs 每个节点保留最大的路径 其他都插入优先队列中
最后记得答案用long long保存
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e5 + 10, mod = 1e9 + 7;
int n, w[N], k;
int h[N], e[N * 2], ne[N * 2], idx;
priority_queue<int,vector<int>,greater<int>> q;
void add(int a,int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int dfs(int u)
{
int maxv = 0;
for (int i = h[u]; ~i; i = ne[i])
{
int son = e[i];
int dep = dfs(son);
if (dep > maxv) //该分支的最长路径比当前最大值大
{
if (maxv != 0)//将当前的长度插入队列 更新最大长度
{
q.push(maxv);
}
maxv = dep;
}
else if (dep <= maxv) q.push(dep);否则将该分支的长度插入队列
}
return maxv + 1;
}
int main()
{
memset(h, -1, sizeof h);
cin >> n >> k;
for (int i = 1; i <= k; i ++ ) scanf("%d", &w[i]);
sort(w + 1, w + 1 + k);
for (int i = 1; i < n; i ++ )
{
int p;
cin >> p;
add(p, i);
}
q.push(dfs(0) - 1);
long long res = 0;//这里要记得开long long
for (int i = 1; i <= k; i ++ )
{
int t = q.top();
q.pop();
res += 1ll * t * w[i];
}
cout << res << endl;
return 0;
}
B.Breaking Branches
您的父母认为,整个星期天在奈梅亨附近的穆克海德(Mookerheide)附近散步会很“有趣”。
尽管您可以通过解决头脑中的编程问题来消磨时间,但您的兄弟姐妹却没有那么奢侈。片刻之后,您的妹妹爱丽丝(Alice)和您的哥哥鲍勃(Bob)感到自己无可救药。他们一起尝试找出是否可以通过游戏打发时间(这个问题后来被称为Bob和Alice Pastime Conundrum)。最后,他们提出了以下简单的游戏。
他们发现长度为n的单个分支将成为游戏的主要对象。或者,Alice和Bob选择一个分支并将其分成两部分,以使两个部分都具有整数长度。最后一个能够打破其中一个棋子的玩家获胜。爱丽丝开始了,因为她是两者中的年轻人。
当然,您已经想到了这个游戏。假设鲍勃发挥最佳,爱丽丝能否赢得比赛?如果是这样,她应该先采取什么行动?
样例输入
2
样例输出
Alice
1
把树枝都变为1需要切n - 1次
如果n是奇数 最后一刀必然是Bob切
反之亦然
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5 + 10, mod = 1e9 + 7;
int n, a[N];
int main()
{
cin >> n;
if (n & 1) puts("Bob");
else
{
puts("Alice");
puts("1");
}
return 0;
}
E.Efficient Exchange
您最近在银行获得了一份新奇的货币工作。人们可以在这里付款,并以各种奇怪的货币存入或提取钱。在工作的第一天,您会帮助来自奈梅贾的客户,奈梅贾是一个微不足道的小国,因其巨大的硬币而闻名,其价值等于10的幂,即1、10、100、1000等。该客户希望相当大的一笔付款,您不希望携带所有这些硬币往返金库。
image_看图王.png
因此,您决定先思考。您和客户一样都有大量的尼吉米亚硬币储备(大多数尼吉米亚公民都非常强大)。现在,您要尽量减少在任一方向上交换的硬币总数,以准确支付客户必须支付的费用。
例如,如果客户要支付83个硬币,则有很多方法可以进行兑换。这是三种可能性:
选项1.客户支付8个价值10的硬币和3个价值1的硬币。这需要交换8 + 3 = 11个硬币。
选项2。客户支付了一个价值100的硬币,您返回了价值10的硬币和7个价值1的硬币。这需要交换1 +1 + 7 = 9个硬币。
选项3。客户支付一枚价值100的硬币和3枚价值1的硬币。您返回2枚价值10的硬币。这需要交换1 + 3 + 2 = 6枚硬币。
事实证明,这样做的最后一种方法需要最少的硬币。
样例输入
83
样例输出
6
(我做的很麻烦 自己都不知道怎么过的)本题用的dp状态机模型
f[i][0] 表示这一位都减去 所需要的硬币数
f[i][1] 表示这一位补足10 所需要的硬币数
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int N = 1e5 + 10, mod = 1e9 + 7;
string x;
vector<int> sum, sum1;
int f[N][2]; //0 减去 1 补足10
int book[20];
int main()
{
for (int i = 0; i <= 9; i ++ ) book[i] = i;
book[10] = 1;
cin >> x;
sum.push_back(0);
for (int i = x.size() - 1; i >= 0; i -- ) sum.push_back(x[i] - '0');
int n = x.size();
for (int i = 1; i <= n; i ++ )
{
f[i][0] = min(
f[i - 1][0] + book[sum[i]], // 前一位减去
f[i - 1][1] + book[sum[i] + min(1, i - 1)]// 前一位补足 此位要+1
// 如果是最开始则不加1 且 此位为10 应消耗一枚 及 sum[10] = 1 下同
);
f[i][1] = min(
f[i - 1][0] + 10 - sum[i],
f[i - 1][1] + 10 - sum[i] - min(1, i - 1)
);
}
cout << min(f[n][0], f[n][1] + 1) << endl;
return 0;
}
J.Jazz it Up!
您与一些朋友一起组建了无调打击乐家和大提琴家乐队。你们在一起已经玩了几年了,但是您对当前的游戏水平感到不满意。在研究一些有趣的新样式时,您会被爵士世界的复杂细节所吸引。
image.png
当然,虽然您不能立即应用所学到的所有新事物,但您想从乐队演奏的音乐中即兴创作一些好的新节奏人物开始。您将在每个小节都有的节奏中弹奏ñn个拍子,然后将每个拍子分成米米笔记。总共,您将拥有纳米Ñ 米每栏的注释。
乐队里的每个人都知道爵士乐中没有广场的空间。因此,条形中的音符数应为无平方数。也就是说,没有数字k> 1ķ>1这样k ^ 2ķ
2
将条形中的音符数量除。
打击乐手已经建议每个小节拍数 ñn;现在由您来决定每个节拍有多少个音符,这些音符不会留出正方形的空间。
在第二个样本中 n = 30ñ=3 0和m = 7米=7。这行得通,因为2≤m <n2≤米<n和m \次n = 210米×ñ=2 1 0没有除数k ^ 2ķ
2
对于任何k> 1ķ>1。
样例输入
3
样例输出
2
思路很简单 但我写的很长 不知道是不是用麻烦了
将n分解质因数 得到质数p1 … pk 求答案为任意其他质数
这里用到 筛质数 和 并查集
先枚举每一个数 i 不是质数 那么让 p[i] = i + 1;
否则 p[i] = i;
分解质因数 每一个质数 p i p_i pi 让 p[ p i p_i pi] = p i p_i pi + 1;
答案就是p[2] 的祖宗节点 (1 0 不是质数)不用枚举
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5 + 10, mod = 1e9 + 7;
int n, primes[N], cnt, p[N];
bool st[N], judge[N];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void get_prime(int x)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes[cnt ++] = i, judge[i] = true;
for (int j = 0; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int main()
{
cin >> n;
get_prime(n);//筛质数
for (int i = 1; i <= n; i ++ )
{
if (judge[i]) p[i] = i;//如果次数
else p[i] = i + 1;
}
p[1] = 2;
for (int i = 2; i <= n / i; i ++ )
{
if (n % i == 0)
{
p[i] = i + 1;
n /= i;
}
}
if (n > 1) p[n] = n + 1;
cout << find(p[1]) << endl;
return 0;
}