C 语言程序设计实践 8.8 W.C之无聊的游戏


AC代码:


#include <stdio.h>  
void Converse(int R[],int n,int p);  
void Reverse(int R[], int from, int to);   
int main()  
{  
    int num[2000],*p=num,n,k,i,j;  
    scanf("%d %d",&n,&k);  
    for (i=0;i<n;i++)  
        *p++=i;//给num数组每个元素赋初值0,1,2...
    p=num;  
    for (i=0;i<n-1;i++){//i代表第(i+1)轮,有n个人则要进行n-1轮  
        for (j=0;j<n-i;j++){//j代表编号,第(i+1)轮共有(n-i)个人  
            if (j+1==((i+1)*k)%(n-i)){
			//因为编号从0开始,而报数从1开始,故要j+1
			//对于对(i+1)轮,被淘汰掉的人报的数是(i+1)*k
			//将 (i+1)*k对人数(n-i)进行取余,只要某人报的是余数则被淘汰 
                Converse(p,n-i,j+1);
				//将编号从j+1开始一直到结束 对其进行逆置 到数组的开头  
                goto flag;// 找到淘汰的人就跳出循环  
            }  
        }  
        flag:;  
    }  
    printf("%d\n",num[0]);// 输出剩下的人的编号  
    return 0;  
} 
 
/*************************************************************************************** 
	找到被淘汰的人的编号j,则要将编号从j+1开始一直到结束的人,将他们放到数组的开头 
	此时数组num可以看成两部分组成 
	A:编号[0]到[j] B:编号[j+1]到[n-i]
	目标: num数组的组成状态由  AB → BA
	类比矩阵的知识有(以下将矩阵X的逆 记为  X^(-1))
	BA=(A^(-1)B^(-1)^(-1)
	因此目标分解为 求A的逆以及B的逆  
	而函数 Reverse 即用来求逆 
****************************************************************************************/  
void Converse(int R[],int n,int p)  
{  
    Reverse(R,0,p-1); // 求 A 的逆   
    Reverse(R,p,n-1); // 求 B 的逆 
    Reverse(R,0,n-1); // 求 A^(-1)B^(-1)的逆 
} 
 
/*一维数组的逆置 就是前后元素调换位置*/  
void Reverse(int R[], int from, int to)  
{  
    int i, temp;  
    for(i=0; i<(to-from+1)/2; i++){//只需循环到一半即可,不然又会交换回来   
        temp=R[from+i];  
        R[from+i]=R[to-i];  
        R[to-i]=temp;  
    }  
}


#include <stdio.h>    
void Reverse(int R[], int from, int to);     
int main()    
{    
    int num[2000],*p=num,n,k,i,j;    
    scanf("%d %d",&n,&k);    
    for (i=0;i<n;i++)    
        *p++=i;
    p=num;    
    for (i=0;i<n-1;i++){
        for (j=0;j<n-i;j++){   
            if (j+1==((i+1)*k)%(n-i)){  
                Reverse(p,0,j);   
    			Reverse(p,j+1,n-i-1);  
    			Reverse(p,0,n-i-1);  
                goto flag; 
            }    
        }    
        flag:;    
    }    
    printf("%d\n",num[0]);
    return 0;    
}   

void Reverse(int R[], int from, int to)    
{    
    int i, temp;    
    for(i=0; i<(to-from+1)/2; i++){
        temp=R[from+i];    
        R[from+i]=R[to-i];    
        R[to-i]=temp;    
    }    
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值