A题
https://codeforces.com/contest/1353/problem/A
看提示找规律 : n = 1, 结果为 0;n = 1,结果为 m;n = 2,结果为 2m
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
int t;
scanf("%d",&t);
while(t--){
int len,sum;
scanf("%d%d",&len,&sum);
if(len==1){
printf("0\n");
continue;
}
if(len==2){
printf("%d\n",sum);
continue;
}
if(len>2)
printf("%d\n",2*sum);
}
return 0;
}
B题
https://codeforces.com/contest/1353/problem/B
将a 数组和 b 数组分别进行排序,比较 a数组的最小数和b数组最大数的大小,判断是否需要交换,若需要,则a 数组从前往小到大逐个交换, b 数组从大到小逐个交换
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int a[40],b[40];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,k;
scanf("%d%d",&n,&k);
for(int i = 0; i<n; ++i){
scanf("%d",&a[i]);
}
for(int i = 0; i<n; ++i){
scanf("%d",&b[i]);
}
sort(a,a+n);
sort(b,b+n);
for(int j = 0; j<k;++j){
if(a[j]<b[n-j-1])
swap(a[j],b[n-j-1]);
else
break;
}
int sum = 0;
for(int i = 0; i<n; ++i){
sum+=a[i];
}
printf("%d\n",sum);
}
return 0;
}
C题
https://codeforces.com/contest/1353/problem/C
思路:所有方块移动到中心花费的次数最小。从中心开始第一层的 8个方块只需移动 1部,第 2层的16个方块只需移动2步,依次类推。因此,通过计算每一圈的总步数,相加即可得到最终结果
#include <iostream>
#include <cstdio>
using namespace std;
#define LL long long
int main(){
int t;
scanf("%d",&t);
while(t--){
LL n;
scanf("%lld",&n);
LL val = n/2;
LL sum = 0;
for(LL i = 1;i<=val; ++i){
sum += i*8*i;
}
printf("%lld\n",sum);
}
return 0;
}
D题
https://codeforces.com/contest/1353/problem/D
本题分割数组的方法类似于二分,因此先进行模拟二分操作,arr[mid].first存储序列长度的大小的相反数(负数便于main函数中对数组进行排序时,不用重新编写排序函数),second存储划分区间后所要赋值的数组元素的下标。模拟二分后再根据子序列的长度(若长度相同,则根据数组元素的下标,小的说明赋值需要优先)进行排序,最后赋值。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
pair<int,int>arr[200005];
int val[200005];
void dfs(int l,int r){
//模拟二分
if(l<=r){
int mid = l+(r-l)/2;
arr[mid].first = l-r-1;
arr[mid].second = mid;
dfs(l,mid-1);
dfs(mid+1,r);
}
}
int main(){
//pair默认排序是从小到大,先比较first,在first相等的情况下比较second
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
dfs(1,n);
sort(arr+1,arr+n+1);
for(int i = 1; i<=n; ++i){
val[arr[i].second] = i;
}
for(int i = 1; i<=n;++i){
printf("%d ",val[i]);
}
printf("\n");
}
return 0;
}
E题
https://codeforces.com/contest/1353/problem/E
满足条件的数的情况:(1)全为 0 (2)第 i 位为 1 ,其余位全是 0 (3)1按周期出现
利用dp[i]记录字串[1,i]区间第i位为1,需要更新原字符串中的值的最小个数(1变0 / 0变1)
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 1000005;
char arr[N];
int dp[N],sum[N];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,k;
scanf("%d%d",&n,&k);
scanf("%s",arr+1);
//利用前缀和计算 1 的个数
for(int i=1; i<=n;++i){
sum[i] = sum[i-1]+(arr[i]=='1');
}
//第 j 位为1,将前面的1都变为 0 需要更新的个数
for(int j = 1; j<=n;++j){
dp[j] = sum[j-1]+(arr[j]=='0');
}
//dp[i]取到第i位(2)和(3)两种情况需要更新的个数的最小值
for(int i = k+1; i<=n;++i){
dp[i] = min(dp[i],dp[i-k]+sum[i-1]-sum[i-k]+(arr[i]=='0'));//上一个 1 的位置
}
int res = sum[n];
//将第 i 位后的 1 都置为 0
for(int i = 1; i<=n;++i){
res = min(res,dp[i]+sum[n]-sum[i]);
}
printf("%d\n",res);
}
return 0;
}