主题:第46次编程比赛第二题(趣味题)
tiancai007 [专家分:0] 发布于 2006-10-27 23:12:00
一座山上周围有n个洞,顺时针编号为0,1,2,……,n-1。
而一只狼从0号洞开始,顺时针方向计数,每遇到m个洞就进洞找兔子,
例如n=5 m=3 狼经过的洞依次为0,3,1,4,2,0
输入n、m。试问兔子有没有幸免的机会?
编写一个完整的程序 n m 由scanf输入
有幸免的机会输出Y
没有输出N
回复列表 (共19个回复)
沙发
FancyMouse [专家分:13680] 发布于 2006-10-27 23:30:00
- - (n,m)=1,即n,m互质,兔子必死。
计算(n,m)用简单的Euclid算法即可。
code就不写了,给其他朋友拿头奖的机会
板凳
gz80 [专家分:0] 发布于 2006-10-28 02:13:00
这道题估计很多人都能猜出来,当m与n互素时答案就必定是‘N’,若是非互素的话答案就是‘Y’了。最主要是证明。这里我用抽象代数里面的群论来证明。
整数(0~n-1)和模n加法组成一个循环群Zn,当群元素m(0<=m<=n-1),能够通过反复多次的模n自加(即(m+m+...+m)mod n)生成群中所有元素,则m称为循环群Zn的生成元。而一个元素是该循环群的生成元的充要条件就是GCD(n,m)=1,证明如下:
元素m是群Zn的生成元<=>
由于数字'1'属于该群中,必定存在一个数整k,使得(k*m)mod n=1
<=>存在整数p,使得k*m+p*n=1
<=>根据数论中的最大公因子定理,则GCD(m,n)=1
因此用辗转相除法判断m,n是否互素,如果互素,则表示0~n-1的任何整数都能由m模n自加多次得到,因此兔子无路可逃。
而且,即使是n<m,其结果也和n,(m mod n)的结果相同,即n=5;m=7的结果与n=5;m=2的结果相同。
程序如下:
int GCD(int x,int y){
int temp,r;
if(x<y) {temp=y;y=x;x=temp;}
for(r=x%y;r;r=x%y)
{
x=y;y=r;
}
return y;
}
int main(int argc, char* argv[])
{
int res=0;int gcd=1;
int m,n;
scanf("%d,%d",&n,&m);
if((n<1)||(m<0)){
printf("Invalid Input");
return 0;
}
else{
if(n==1)res=0;//只有一个洞,兔子无处藏身
else{
if(m==0)res=1;//m=0表示狼不前进,兔子可在除0好洞外其余地方藏身
else {
gcd=GCD(n,m);
if(gcd==1) res=0;
else res=1;
}
}
}
printf("%c\n",res?'Y':'N');
return 0;
}
3 楼
neverPE [专家分:1620] 发布于 2006-10-28 09:52:00
只想到暴力算法,O(n)的,不知道有什么数学方法可以在O(1)内算出来。
4 楼
zheni [专家分:60] 发布于 2006-10-28 10:10:00
#include <stdio.h>
int main(void)
{
int n,j,k=0,flag=0,m,*p,*head,i;
scanf("%d %d",&n,&m);
p=(int*)malloc(sizeof(int)*n);
for(i=0;i<n;i++)
p[i]=0;
*p=1;
j=m;
while(j!=0){
p[j]=1;
j=(j+m)%n;
}
for(i=0;i<n;i++){
if(p[i]==0){
flag=1;
break;
}
}
if(flag==1)
printf("%c",'Y');
else
printf("%c",'N');
return 0;
}
5 楼
tgbtgb [专家分:490] 发布于 2006-10-28 11:01:00
#include"stdio.h"
main()
{int m,n,i,j,k,t,x,s[10000][2];
scanf("%d %d",&n,&m);
for(i=0;i<n;i++)
{s[i][1]=i;
s[i][0]=0;}
x=0;
for(i=0;i<10000;i++)
{
j=i%m;
if(j==0)
{k=i%n;
for(t=0;t<n;t++)
if(s[t][1]==k)
s[t][0]=1;
}}
for(i=0;i<n;i++)
if(s[i][0]==0)
x++;
if(x!=0)
printf("Y\n");
else
printf("N\n");
}
6 楼
redlives [专家分:6090] 发布于 2006-10-28 11:53:00
#include "stdio.h"
int main(int argc, char* argv[])
{
int m,n;
int num = 0;
printf("Input n and m:\n");
if(!scanf("%d,%d",&n,&m))
printf("ERROR!");
int *a = new int[n];
for(int i = 0;i < n;i ++)
a[i] = 1;
for(i = m - 1;n - num > 0;i += m)
{
for(;i >= n;)
i = i - n;
if(a[i] != -1)
{
a[i] = -1;
num ++;
if(num == n)
printf("兔子不能幸免.狼最后进入的洞是%d.\n",i%n);
}
else
break;
}
if(num != n)
{
printf("兔子幸免的机会为: %d/%d\n可以幸免的洞有:\n",n-num,n);
for(i = 0;i < n;i ++)
{
if(a[i] != -1)
printf("%d,",i);
}
printf("\n");
}
delete []a;
return 0;
}
7 楼
ITER [专家分:680] 发布于 2006-10-28 17:10:00
#include<iostream>
using namespace std;
/*
因为题目没给出n的范围,所以我只设了长度为1001
只能测n<=1000的情况 具体情况请题主自由设定tag长度
*/
int deal(int m,int n,int tag[])
{
int drift(m);
int count(1);
while(drift!=0)
{
if(drift>=n)
drift=drift%n;
if(0==tag[drift])
{
count++;
tag[drift]=1;
}
drift+=m;
if(drift>=n)
drift=drift%n;
}
if(count==n)
return 0;
else return 1;
}
main()
{
int m,n;
cout<<"请输入m"<<endl;
cin>>m;
cout<<"请输入n"<<endl;
cin>>n;
int tag[1001];
memset(tag,0,sizeof(tag));
if(deal(m,n,tag))
cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
8 楼
magicalking [专家分:150] 发布于 2006-10-28 17:30:00
#include<iostream>
using namespace std;
int main()
{
int n,m,sum=0,i,j;
cin>>n>>m;
int *p=new(int[n]);
for (i=0;i<n;i++)p[i]=1;
j=i=0;
while (sum!=n)
{
if (i%m==0)
if (p[j])
{
p[j]=0;
sum++;
}
else break;
i++;
j=i%n;
}
cout<<((sum==n)?'N':'Y');
delete[] p;
}
9 楼
hah422 [专家分:0] 发布于 2006-10-28 22:30:00
#include<iostream>
using std::cout;
using std::cin;
using std::endl;
unsigned long gcd(unsigned long a, unsigned long b)
{
if(a<b)
{
unsigned long d;
d = b;
b = a;
a = d;
}
unsigned long c=0;
while(c = a % b)
{a = b;
b = c;
}
return b;
}
int main()
{ cout<<"Please Press 0 to Exit"<<endl;
for(unsigned long ula=0;cout<<"The N is: ";
cout<<"Please Press 0 to Exit"<<endl)
{
cin>>ula;
if(!ula) {cout<<"N not ex to no ul int!!!";
exit(-1);}
cout<<"The M is: ";
unsigned long ulb=0;
cin>>ulb;
if(!ulb) cout<<"M not ex to no ul int!!!";
if(gcd(ula,ulb)==1)
cout<<"N"<<endl;
else cout<<"Y"<<endl;
}
return(0);
}
***********************************************************************
在做这个过程中 我发现了一个问题, 我的电脑是 winxpsp2 + Dev C++4.9.9.2
为了 看看 整形的具体情况 我做了一个测试 发现以下奇怪问题,希望有人帮我解答下:::::
long long int 的sizeof 值为8 可是实际我弄了下 发现实际取值如下:
(-2的31次方+1)到(+2的31次方-1)
unsigned long long sizeof值也是8 实际却取值 如下:
0 到(+2的31次方-1)
而不是理论的 0到 (+2的32次方-1)
long int 的sizeof 值是4 可是实际取值同long long int 一样;
unsigned long int 的sizeof 值也是4 可实际取值也和unsigned long long 一样;
***************************
相当疑惑中************************************
10 楼
xieyong456 [专家分:2620] 发布于 2006-10-28 23:06:00
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <cstdio>
#include <cstring>
#include <ctime>
void Init(int num[], int n);
void Search(int num[], int n, int m);
void Judge(int k, int n);
int main(void)
{
int n, m;
int *num;
clock_t start, end;
start = clock();
printf("请输入洞的数量和隔几个洞找n和m : ");
scanf("%d%d", &n, &m);
num = (int *)malloc(n * sizeof(int));
Init(num, n);
Search(num, n, m);
end = clock();
printf("时间:%f秒\n", (end-start)/(double)CLK_TCK);
free(num);
return 0;
}
void Init(int num[], int n)
{
int i;
for(i = 0; i < n; i++)
{
num[i] = i;
}
}
void Search(int num[], int n, int m)
{
int count, k, l, i;
int *s;
s = (int *)malloc(n * sizeof(int));
count = 0;
k = 0;
l = 0;
for(i = 0; l < n; i++)
{
if(i == 0)
{
;
}
else
{
count++;
if(count % m == 0)
{
s[k++] = num[i % n];
// printf("%4d", num[i % n]);
if(i >= n && num[i % n] == 0)
break;
else
l++;
}
}
}
Judge(k, n);
}
void Judge(int k, int n)
{
if(k < n)
{
printf("\nY\n");
}
else
{
printf("\nN\n");
}
}
我来回复