当前位置 : 主页 > 大数据 > 区块链 >

Codeforces Round #507 B. Shashlik Cooking

来源:互联网 收集:自由互联 发布时间:2021-06-22
这道题,真香。 (话说shashlik好像是毛子们/东欧地区人民热爱的,一种类似于烤串的美食,wiki上的图片看起来很香的样子) 嗯大概就是这个。 题目大意: Miroslav正在烤串。 众所周知

这道题,真香。

(话说shashlik好像是毛子们/东欧地区人民热爱的,一种类似于烤串的美食,wiki上的图片看起来很香的样子)

嗯大概就是这个。

题目大意:

Miroslav正在烤串。

众所周知烤串是要翻动的。

有n个烤串,每个串一开始都是正面朝上的。对于某个烤串进行翻动操作,会使这个串以及相邻左右k个串都被翻动。

翻动会使正面朝上的串翻到反面,反面朝上的串翻到正面。

求最少翻动几次能够将n个串全部翻到反面。

输出最少翻动次数,以及翻动哪些串。

程式化的描述:

给定一个初始为0的数组,每次对 $ i $ 操作会使 $ [i-k,i+k] $ 之间的所有数字取反(0->1,1->0),最少操作多少次能够将整个数组变为1。

输出最少操作次数,以及操作数组的哪些元素。

题解:

首先是求最小操作次数。不难发现,每个串 $ i $ 都控制着 $ [i-k,i+k] $ 的区域。也就是说,每个串控制长度为 $ k*2+1 $ 的区域。

我们从1开始,枚举使用多少个长度为 $ k*2+1 $ 的区域,能把 $ n $ 覆盖掉。

$ ans $ 为需要翻转的烤串数量(最少翻动次数)。

int ans=0;
while(ans*(2*k+1)<n)ans++;
printf("%d\n",ans);

然后是求这些烤串的位置。

先求最左边的烤串的位置 $ l $ ,从1到 $ k+1 $ 枚举,因为每个烤串之间距离是已知的 $ (2k) $ ,所以可以算出最右边的烤串位置为 $ l+(ans-1)((2*k)+1) $

如果最右边的位置+k大于等于n,就可以了。

int l=1;
for(;l<=k+1 and (l+(ans-1)*((2*k)+1)+k)<n;l++){}

最后从 $ l $ 开始,下一个串的位置等于上一个的位置+ $ (2*k)+1 $ ,逐个输出就好了。

printf("%d ",l);
while(l+k<n){
    l=l+(2*k)+1;
    printf("%d ",l);
}
网友评论