题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1443
题目大意:
给你k个好人和k个坏人,你给出一个最小的m的值令坏人全部杀死,而好人不能被杀死。然后其中的规则如下的例子来解释:
比如题目说的:k=3,m=5那么会有1,2,3,4,5,6六个人,
m=5的第一遍循环就是,将5号杀死。
然后再从5号开始数下一个第五个的人,将其杀死,即->6->1->2->3->4故,第二次杀的是4号
接着就是->6->1->2->3->6【注意:因为5号已经去世了,所以不可能再遍历到5号】所以这次死亡的是6。
123是好人,456是坏人,456在m=5的情况下全部阵亡,好人都活着。所以这个m是符合题目条件的。
这上面的就是m和k的关系
思路参考来源:
https://blog.csdn.net/liujian20150808/article/details/50932817
思路
首先就是观察一下规律。
先将所有犯人设置为0,1,…,k-1,k,…, 2k-2,2k-1
为什么不是从1开始到2k呢?
如果设置为1到2k的话,那么第一个处死的人位置p就是m%n(n为这里的犯人总人数也就是2k),那么如果m恰好是等于n的话,也就是最后一个处死,那么这里的值就为0了,那么也就是说当m%n时我们还得重新令p这个值等于n。多加了一步操作。
如果设置为0…到2k-1的话就可以直接得到p的值,就不用处理最后一个值等于0的情况了
由于题目要求是所有坏蛋总是在好人之前出列,所以我们可以将好人圈定起来,将好人定为非法区域。
所以我们可以设start和end两个变量来记录好人编号的起止,所以一开始的时候可将这两数初始化为:
int start = 0 ; int end = k-1;
我们可以将第一个出去的位置定为kill,第一个循环中的kill = (m-1)%n【n为总人数,2*k】,
从上面的题目大意中的例子大家可以知道,就是下次循环找处死人的位置是以这个为起点的。那么比如紧接着第一个循环之后的就是第二个循环,找的顺序将会为kill+1,kill+2,kill+3…,kill+2*k-2
这个2k-2怎么来的?
就是把这群犯人想象成一个环,第二个又从第1个开始找,1->2->…>2k-2,
2k-2是2k-1的左边一个,其实就是第二个循环的最后一个了,相当于循环回来了。
然后通过观察我们会发现,每次循环好人的范围都会跟着变,但是嘞,好人的起始点和终点的相对位置是不会变的,所以我们每次的循环只需要更新好人区域的值,判断kill这个位置是否在好人区域中就行了。
然后我们可以看到,第二次查找的循环每个都减去kill+1的值就会变为:
0,1,2,3…,2*k-2又变为了第一次的查找的情况了
那么也就是说,start也符合这种情况,start=start-(kill+1)【是上一次的start减去上一次的kill+1,就得到了这次的start】
代入kill=(m-1)%n,得到start=start-((m-1)%n+1)=start-(m%n-1%n+1)=start-(m%n)
然后防止start为负数,所以,start=(start-m%n+n)%n
为什么start=start-(m%n)可以变为start=(start-m%n+n)%n?
比如证明:(x-a)%n = (x-a+n)%n
右边等于((x-a)%n+n%n)%n = (x-a)%n
等于左边,因此得证。
所以只需要将a看成m%n带入这个证明中就可以了
所以最终start=(start-m%n+n)%n,end=(end-m%n+n)%n
ac代码:
#include <stdio.h>
int judge(int k, int m){
int start = 0;//记录好人的初始位置
int end = k-1;//好人最后一个位置
int kill;
for(int i = 2*k;i > k;i--){
kill = (m-1)%i;//得到处死的位置
if(kill>=start&&kill<=end){
return 0;
}
start = (start-(m%i)+i)%i;
end = (end-(m%i)+i)%i;
}
return 1;
}
int main(){
int f[14];
int k;
for(int i = 1;i < 14;i++){
for(int j = 1;;j++){
if(judge(i,j)==1){
f[i] = j;
break;
}
}
}
while(~scanf("%d",&k)){
if(k == 0)break;
printf("%d\n",f[k]);
}
return 0;
}
【附录】由于个人觉得参考那位大神的思路的比较多但也算有自己的理解,也不知道是算转载或是原创,暂且定为原创。若引起本人不适,请与我联系,并删除此帖。