博弈论习题分析

博弈论习题分析

      推荐文章论文:http://wenku.baidu.com/view/b0a2421ca76e58fafab00359.html

 

一:URAL1180.取石子游戏

1180.取石子游戏
两个Nikifor在玩一个好玩的游戏。
这里有一堆总数为n的石子。
两个Nikifor轮流从石子堆中取石子。
每一个人可以取任意2的非负整数次幂个石子。
取到最后一个石子的人获胜。
你现在写一个程序来判断谁会赢。

输入

一个整数n(n<=10^250)

输出

如果第一个取石子的Nikifor赢那么在第一行输出1,
同时在第二行输出,保证他赢的情况下第一次最少要取的石子数。
如果第二个Nikifor赢,则只输出2。

样例输入

8

样例输出

1
2

【分析】:

    当n为三的倍数时,第一个Nikifor一定会输,否则当第一个Nikifor第一次取n mod 3 时一定会赢。

    证明:对于n=0,n=1,n=2时,命题显然成立。现证明当对于任意的i(0<=i<=n-1)有命题成立,命题对于n也成立。

    当n不是三的倍数时,由于n mod 3一定为2的非负整数次幂,所以当第一个Nikifor第一次取n mod 3 个石子时,一定可以时当前状态变为必败状态,因为对于任意的i(0<=i<=n-1)有命题成立。当n是三的倍数时,由于前面的必败状态m一定是3的倍数,而 n-m 一定含有质因数3,即n-m一定不是2的整数次幂,因此当前的n一定不能变为必败状态,因此,当前的状态为必败状态。

【代码】:

#include<stdio.h>
#include<string.h>
int main()
{
    char s[251];
    scanf("%s",&s);
    int i,sum=0;
    for(i=0;i<strlen(s);i++)
        sum+=(s[i]-48);//
    if(sum%3==0)
        printf("2");
    else
        printf("1\n%d",sum%3);
    return 0;
}


 

二:URAL/1023Background

 

时间限制:2s内存限制:16MB

Background

Yekaterinburg获得了2032年夏季奥运会的举办权。由于允许俄罗斯(举办国)对竞赛项目进行一些小的修改。现打算修改“Button”这个新项目的规则。规则很简单,在2个对手前有一堆扣子(k个),2人轮流取走扣子,同一时间,某人能取走1至L个扣子。取走最后一个扣子的为胜者。作为奥运会项目,规则应该比通常玩的要难一点。先走者可以设定数K(就是总共有k个扣子),3<=K<=100 000 000.后走者可以设定数 L,2 ≤ L < K

Problem

现在要紧的问题是,请你写一个程序,帮助后走者做出抉择。换言之,当给出K后,你的程序能给出数L,使到后走者能获胜。例如, 如果只有3个扣子,后走者把L定为2,有必胜把握。事实上,如果先走者取了1个扣子,那么后走者可以取剩下的2个扣子,后走者胜。如果先走者取了2个扣子,那么后走者取1个,也是后走者胜。

Input

输入只包含一个整数K,扣子的总数。

Output

输出L。每次最多能取走的扣子总数,要求保证后走者必胜。假如有多个答案,输出最小的。如果不存在保证能必胜的L,则输出0。

Sample Input

3

Sample Output

2

Sample Input

908640443

Sample Output

908640442
 
【其他数据】:
      10    ans:4    
      100   ans:3    
      17    ans:16    
      26    ans:12    
      200   ans:3    
      14    ans:6 
【代码】:
#include<stdio.h>
int n,ans;
int main()
{
	scanf("%d",&n);
	for(int i=3;i*i<=n;i++)
	if(n%i==0)
    {
		ans=i-1;
		break;
	}
	if(!ans)
		if(n&1)	ans=n-1;
		else	ans=n/2-1;
	if(ans<2)	ans=n-1;
	printf("%d\n",ans);
	return 0;
    //0.953 108 KB
	
}
#include<stdio.h>
int main()
{
      int i=3,a;
      scanf("%d",&a);
      while(a%i!=0)
           i++;
      printf("%d",i-1);
      return 0;
}
//0.015 108 KB 



【分析】:

        这是一道经典的博弈的题目

        首先我们想如果给定了k,l,那么怎么确定第一个人是不是必胜的,如果是的那他第一次应该取几个?显然是 k mod (l+1)个,如果 k mod (l+1)=0那么显然是必输的。我们这样看,第一个人第一次取走k mod (l+1)后,剩下的button(l+1)的倍数,这时无论第二个人取几个(设他取i个),第一个下一次都可以取(l+1-i)个,使剩下的button也是(l+1)的倍数,这样第一个人一定能拿到最后一个。

      所以如果k mod (l+1)=0

      那么第一个人第一次只能取0个,显然是输的。枚举约数的话,我们从1sqrt(k)枚举就可以了,但是按题意3<=(l+1),我们会忽略掉2这个约数(如果k是偶数),也同时会忽略掉 k div 2这个约数,最后要特殊判断一下。

 

转载注明出处:http://blog.csdn.net/u011400953

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值