B - Power Sequence
1.题意
由n个正整数组成的序列,如果存在一个正整数c使得ai = c的i次方(0 <= i <= n - 1),这个序列就称为正确序列。允许的操作为①对序列排序②将序列中某个值加一或减一,这个操作代价为1。操作都可以进行无限次,求将给定序列变成正确序列所付出的最小代价。
2.题解
其实就是找到一个正整数c,使得ai - c的i次方的绝对值的和最小(0 <= i <= n - 1)。我们把序列按从小到大排序找出c肯定优于乱序找出c,数据范围不大,可以暴力枚举。如果我们令c等于1,这时我们付出的代价最大为1e5×1e9 = 1e14,我们把c从1枚举到1e14,当c的n次方超过1e14时,答案会劣于c为1的情况,因此我们只需把c从1枚举到1e14的1/n次方向下取整。
3.代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int maxn = 1e5 + 5; 5 const ll INF = 1e14; 6 int a[maxn]; 7 ll power[maxn]; 8 int main(){ 9 int n; 10 scanf("%d", &n); 11 for(int i = 1; i <= n; i++) { 12 scanf("%d", &a[i]); 13 } 14 sort(a + 1, a + 1 + n); 15 int R = floor(pow(INF, 1.0 / n)); 16 ll sum = 0; 17 ll ans=INF; 18 for(int i = 1; i <= R; i++) { 19 sum = 0; 20 power[0] = 1; 21 for(int j = 1; j <= n; j++) { 22 power[j] = power[j-1] * i; 23 sum += abs(a[j] - power[j - 1]); 24 } 25 ans = min(ans, sum); 26 } 27 cout << ans << endl; 28 29 return 0; 30 }
F - Basketball Exercise
1.题意
给定一个2*n的矩阵,按从左到右的顺序从中选择若干数,且选择的任意两个数上下不相邻且左右不相邻,求这些数的和最大是多少。
2.题解
注意到可以选择的球员编号是严格递增的,因此可以把状态的第一维定义为球员编号,第二维描述编号同为i的两名球员的选取情况。dp[i][0/1/2]表示选取了编号在i及以前的球员,所能得到的身高总和最大值。其中,第二维的0表示编号为i的球员一个都不选;1表示只选第一行的i号队员;i表示只选第二行的i号队员。
状态转移方程:
dp[i][0]=max{dp[i−1][0],dp[i−1][1],dp[i−1][2]}
dp[i][1]=max{dp[i−1][0],dp[i−1][2]}+height[i][1]
dp[i][2]=max{dp[i−1][0],dp[i−1][1]}+height[i][2]
3.代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int maxn = 1e5 + 5; 5 int n; 6 ll h[100005][3]; 7 ll dp[100005][3]; 8 int main() { 9 scanf("%d", &n); 10 for(int i = 1; i <= n; i++) { 11 scanf("%lld", &h[i][1]); 12 } 13 for (int i = 1; i <= n; i++) { 14 scanf("%lld", &h[i][2]); 15 } 16 dp[1][0] = 0; 17 dp[1][1] = h[1][1]; 18 dp[1][2] = h[1][2]; 19 for(int i = 2; i <= n; i++) { 20 dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][1], dp[i - 1][2])); 21 dp[i][1] = max(dp[i - 1][0], dp[i - 1][2]) + h[i][1]; 22 dp[i][2] = max(dp[i - 1][0], dp[i - 1][1]) + h[i][2]; 23 } 24 printf("%lld ", max(dp[n][0], max(dp[n][1], dp[n][2]))); 25 26 return 0; 27 }