版权声明:Andy https://blog.csdn.net/Alibaba_lhl/article/details/82491647
Input
7 2
Output
2
1 6
Input
5 1
Output
2
1 4
Source::Click here
题意
给你n串羊肉串,它们的编号依次为1,2,3,,,n。羊肉串初始状态全为正面,你的任务是将所有的羊肉串翻转过来。规则是:当每次选择一个位置pos进行翻转,pos-k和pos+k的位置都会被翻转。求最少多少次能将所有的羊肉串全部翻转过来。、
思路
这个题可以分类讨论。对n和2k+1的关系进行讨论。
- 当n<=2k+1,进行一次就可完成。因为选择一个pos,最大的覆盖范围是2k+1.
- 当n>2k+1,需要对r(r=n%(2k+1))进行讨论 ①:当r<k+1时,初始位置从1开始,每隔2k+1选定一个。原因:当余数为r<k+1时,可将序列表示为:k+1 2k+1 2k+1 2k+1 ,,, 2k+1 X (最后一组用X表示 k+1<=X<=2k,即可选择一个pos,不然会出现对同一个执行两次) ②:当r>=k+1时,初始位置从k+1开始,每隔2k+1选定一个。
AC Code
#include<bits/stdc++.h>
using namespace std;
int n, k, r, idx;
vector<int> V;
int main()
{
scanf("%d%d",&n,&k);
r = n % (2 * k + 1);
if(r == 0) r += (2 * k + 1);///当n是2k+1的整数倍,将余数记为2k+1用于后续操作
if(n <= 2 * k + 1)///当n小于2k+1时,即即一次就能完成操作,如(左边k个,1,右边k个,即可以进行一次就能完成操作)
{
puts("1");
printf("%d\n",min(n, k + 1));///若1+k<n,则应输出n
return 0;
}
else if(r < k + 1) idx = 1;///当n大于2k+1且余数小于k+1,为了避免出现对同一个操作两次的情况出现,起始位从1开始
else idx = k + 1;///当n大于2k+1且余数大于等于k+1,
for( ; idx <= n; idx += (2 * k + 1)) V.push_back(idx);///将选定的序号(每隔2k+1)存入vecotr中
int len = V.size();
printf("%d\n",len);
for(int i=0; i<len; i++)
{
if(i==0) printf("%d",V[i]);
else printf(" %d",V[i]);
}
return 0;
}