A. The Man who became a God
题意:Kars是个顶尖的发明家,他对村庄里狭隘的思维方式感到厌倦和愤怒,因为村民们满足于现状,不努力成为完美的生命形式。Kars希望通过改造自己的身体成为完美的生命形式。然而,有n位村民对他的想法持怀疑态度。第i位村民对他抱有ai的怀疑。每位村民个别地都害怕Kars,所以他们组成团体以增强力量。 从l到r的村民团体的力量定义为f(l,r),其中 f(l,r)=|al−al+1|+|al+1−al+2|+…+|ar−1−ar|。 这里|x−y|表示x-y的绝对值。只有一位村民的团体力量为0。 Kars想要将村民分成恰好k个连续的子团体,使得它们的力量之和最小化。具体来说,他需要找到k-1个正整数1≤r1<r2<…<rk−1<n,使得f(1,r1)+f(r1+1,r2)+…+f(rk−1+1,n)达到最小值。帮助Kars找出f(1,r1)+f(r1+1,r2)+…+f(rk−1+1,n)的最小可能值。
输入:
第一行包含一个整数t(1≤t≤100)——测试用例的数量。下面是每个测试用例的描述。 每个测试用例的第一行包含两个整数n和k(1≤k≤n≤100)——村民的数量和他们必须分成的团体数。 每个测试用例的第二行包含n个整数a1,a2,…,an(1≤ai≤500)——每位村民的怀疑程度。
输出:
对于每个测试用例,输出一个整数——所有团体力量之和的最小可能值,即f(1,r1)+f(r1+1,r2)+…+f(rk−1+1,n)的最小可能值。
思路:求出相邻两个元素的差值,去掉前m个大的差值以后的差值和即位答案。
AC代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 110;
int t, n, k, sum;
int a[N], b[N], c[N];
int main()
{
cin >> t;
while(t --)
{
cin >> n >> k;
for(int i = 1; i <= n; i ++)
{
cin >> a[i];
}
for(int i = 1; i <= n; i ++)
{
b[i] = abs(a[i + 1] - a[i]);
}
for(int i = 1; i <= n - 1; i ++)
{
c[i] = b[i];
}
sort(c, c + n);
for(int i = 1; i <= n - k; i ++)
{
sum += c[i];
}
cout << sum << endl;
sum = 0;
}
return 0;
}
B. Hamon Odyssey
题意:Jonathan正在与DIO的吸血鬼手下战斗。有n个吸血鬼,他们的力量分别为a1,a2,…,an。
用(l,r)表示由索引从l到r的吸血鬼组成的组。Jonathan意识到,任何这样的组的力量取决于它们最弱的环节,即按位与操作的结果。更正式地说,组(l,r)的强度等级定义为f(l,r) = al & al+1 & al+2 & … & ar。其中,&表示按位与操作。
因为Jonathan想要快速击败吸血鬼手下,他会将吸血鬼分成连续的组,使得每个吸血鬼恰好属于一个组,并且各组的力量总和最小。在所有可能的分组方式中,他希望找到分组数量最多的方式。
给定每个吸血鬼的力量,找到在所有可能的分组方式中具有最小力量总和的最大分组数量。
输入:
第一行包含一个整数t(1≤t≤104)- 测试用例的数量。后面是每个测试用例的描述。
每个测试用例的第一行包含一个整数n(1≤n≤2⋅105)- 吸血鬼的数量。
每个测试用例的第二行包含n个整数a1,a2,…,an(0≤ai≤109)- 每个吸血鬼的力量。
所有测试用例中n的总和不超过2⋅105。
输出:
对于每个测试用例,输出一个整数 - 在所有可能的分组方式中具有最小力量总和的最大分组数量。
思路:首先如果分成一段以上,那么一段的与一定等于零。因为如果分出的段中有非零值,那这些段的总和一定比全部与起来大(因为与运算不会使得值变大)。所以如果全部与起来不等于0,答案就是1。否则的话,就直接从前往后去找,找到一段与起来等于1的,就分一段即可。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200010 , INF = 0x3f3f3f3f , Mod = 998244353;
int main()
{
ll n, k;
cin >> n;
vector<ll> v(n+1);
for(int i = 1; i <= n; i ++)
{
cin >> v[i];
}
ll now = v[1];
for(int i = 2; i <= n; i ++)
{
now &= v[i];
}
if(now!=0)
{
cout << 1 << endl;
return 0;
}
ll tmp = v[1];
ll ans = 0;
for(int i = 2; i <= n; i ++)
{
if(tmp == now)
{ ans ++;
tmp = v[i];
continue;
}
tmp &= v[i];
}
if(tmp == now) ans ++;
cout << ans << endl;
}