《健指算法》(一)反转牌面

《《健指算法》(一)反转牌面》

《《健指算法》(一)反转牌面》

《《健指算法》(一)反转牌面》

《《健指算法》(一)反转牌面》

《《健指算法》(一)反转牌面》

《《健指算法》(一)反转牌面》

    有100张按顺序写着1-100数字的牌,一开始所有牌都是背面朝上。接下来,从第3张牌开始,隔2张牌翻牌(原本正面的变反面,反面的变正面)。然后又从第4张开始,隔三张牌翻牌。一直做下去,从第n张牌开始,每隔n-1张牌翻牌,直到没有可翻动的牌为止,求所有背面朝上的牌的数字?                                            

《《健指算法》(一)反转牌面》   

《《健指算法》(一)反转牌面》

《《健指算法》(一)反转牌面》

思路:我们看到,从第n张牌开始往后,隔n-1张牌翻牌,是一直从左往右处理牌,所以只要用一个数组来存储这些牌,数组下标为牌的数字,下标对应的数组元素代表牌的正反面状态,然后按顺序处理对牌进行“翻转“就可以了,如果牌面朝上,对应下标元素就为1,否则牌面朝下,对应下标元素就为0。

#include <stdio.h>

int main (int aggc, char const* argv[])
{
	int arr[101]={0}; /*0表示反面,1表示正面*/ 
	int i, j;
	
	/*初始化牌组*/
//	for (i=1; i<=100; i++) {
//		arr[i]=0;
//	}

	/*输出牌组初始值看看*/
	printf("初始牌组:"); 
	for (i=1; i<=100; i++) {
		printf("%d ", arr[i]);
	}
	printf("\n");
	
	/*开始翻牌*/
	for (i=2; i<=100; i++) {
		for (j=i; j<=100; j+=i) {
			arr[j]=!arr[j];
		}
	}
	
	/*输出最后牌组*/
	printf("\n最后牌组:"); 
	for (i=1; i<=100; i++) {
		printf("%d ", arr[i]);
	}
	printf("\n");
	
	printf("\n所有背面朝上的牌的数字:");
	for (i=1; i<=100; i++) {
		if (arr[i]==0) {
			printf("%d\t", i);
		}
	} 
	return 0;
}

《《健指算法》(一)反转牌面》

《《健指算法》(一)反转牌面》

#include <stdio.h>

int main (int aggc, char const* argv[])
{
	int arr[101]={0}; /*0表示反面,1表示正面*/ 
	int i, j, number;
	
	/*初始化牌组*/
//	for (i=1; i<=100; i++) {
//		arr[i]=0;
//	}

	/*输出牌组初始值看看*/
	printf("初始牌组:"); 
	for (i=1; i<=100; i++) {
		printf("%d ", arr[i]);
	}
	printf("\n");
	
	printf("\n请输入要反转到第n次牌:");
	scanf("%d", &number);
	/*开始翻牌*/
	for (i=2; i<=number; i++) {
		for (j=i; j<=100; j+=i) {
			arr[j]=!arr[j];
		}
	}
	
	/*输出最后牌组*/
	printf("\n最后牌组:"); 
	for (i=1; i<=100; i++) {
		printf("%d ", arr[i]);
	}
	printf("\n");
	
	printf("\n所有背面朝上的牌的数字:");
	for (i=1; i<=100; i++) {
		if (arr[i]==1) {
			printf("%d\t", i);
		}
	} 
	return 0;
}

 

《《健指算法》(一)反转牌面》

《《健指算法》(一)反转牌面》

我们从上面结果可以看到,从第2开始翻到第100,也就是翻到所有牌不再变动后,结果是1、4、9、16、25、36、49、64、81、100。这些数是不是很有规律?它们分别是1²、2²、3²。。。。。9²,10²。都是平方数。

      还有一个规律,我们的牌一开始全是背面朝上,如果牌进行了奇数次反转,最后是正面朝上的;如果牌进行了偶数次反转,最后是反面朝上的。我们题目问最后反面朝上的牌的数字,也就是说寻找反转了偶数次的牌有哪些。

      那么怎么计算牌的最后反转次数是奇数还是偶数呢?我们知道某张牌经过反转后,反面朝上的话,那么就是经过偶数次反转,如果这个的翻牌间隔k这个牌数N的约数,那么这张牌数一定能经过k个间隔到达N并进行反转操作(表述的不好- -、)。所以会进行翻牌操作。

      接着我们用逆推的思想看,4的约数有1、2、4三个,9的约数有1、3、9、三个,16的约数有1、2、4、8、16五个……也就是说,我们要找平方数且它的约数个数是奇数个的数(当然你也可以从2开始,寻找约数是偶数个的数)。

      所以根据这个思路,我们可以把代码简化为:

#include <stdio.h>

int main (int aggc, char const* argv[])
{
	int arr[101]={0}; /*0表示反面,1表示正面*/ 
	int i, j;
	
	/*初始化牌组*/
//	for (i=1; i<=100; i++) {
//		arr[i]=0;
//	}

	/*输出牌组初始值看看*/
	printf("初始牌组:"); 
	for (i=1; i<=100; i++) {
		printf("%d ", arr[i]);
	}
	
	printf("\n\n所有背面朝上的牌的数字:");
	for (i=1; i<=100; i++) {
		arr[i]=0;
	for (j=1; j<=100; j++) {
		/*如果是约数,就进行翻牌操作*/
		if (i%j==0) {
			arr[i]=!arr[i];
		}
	}
	if (arr[i]==1) {
		printf("%d ", i);
		}	
	} 
}

《《健指算法》(一)反转牌面》

完整代码在个人代码云:

https://gitee.com/justinzeng/codes/mo4cw3kre618lanhfztdp31

https://gitee.com/justinzeng/codes/bdq42s6w91yipekl8no5h21

    原文作者:魔术师发牌问题
    原文地址: https://blog.csdn.net/justinzengTM/article/details/83996332
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞