狱吏问题(小白code记录)

狱吏问题

Description

某国王大赦囚犯,让一狱吏n次通过一排锁着的n间牢房,每通过一次,按所定规则转动n间牢房的某些门锁,每转动一次,原来锁着的门被打开,原来打开的门被锁上,通过n次后,门开着的,牢房中的犯人放出,否则犯人不得释放。 转动门锁的规则是这样的,第一次通过牢房,从第1间开始要转动每一把门锁,即把全部的锁打开;第2次通过牢房时,从第2间开始转动,每隔一间转动一次;…;第k次通过牢房时,从第k间开始转动,每隔k-1间转动一次;问通过n次后,哪些牢房的锁是打开的? Input 题目包含多组数据,每组数据包含一个整数n,n不超过1000000,牢房编号从1开始。不超过100组样例。 Output 要求输出牢房的编号。

Sample Input

5

Sample Output

2
1 4

第一次尝试(模拟算法)

#include 
using namespace std;

int main() {
	int n;
	bool *door;
	cin >> n;
	door = new bool[n+1];//动态分配内存空间
	for (int i = 0; i <= n; i++) {
		door[i]=false;
	}//false代表门关,true代表门开,初始化

	for (int i = 1; i <= n; i++) {
		for (int j = 1; i*j <= n; j++) {
			door[i*j]= !door[i*j];
		}//按规则操作
	
	}
	for (int i = 1; i <= n; i++) {
		if (door[i]) {
			cout << i << ends;
		}
	}
	cout << endl;
	
	delete[] door;//释放
	system("pause");
	return 0;
}

反思

做题时发现第i次操作,就从第i山门开始,将其倍数编号的的门进行“取反”操作,感觉会有些规律。做完后带入较大数字后发现,输出结果都是平方数。于是期望能找到比较本质的数学解法。然后发现,对于某一个编号的门i,对它进行思考,能影响它的无非是它的因子,问题就转化成求每扇门的“因子”个数。例如,9有1,3,9三个;10有1,2,5,10四个;因为初始状态为false(关闭)也就是说,因子个为奇数的门就是打开的,偶数为闭合的。而显然,只有平方数的因子个数是奇数。
于是代码就可以改为:

#include 
#include 
using namespace std;

int main() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		if (sqrt(i) == int(sqrt(i)))
			cout << i << ends;
	}

	system("pause");
	return 0;
}

编程新手刷题记录2019.4.21

你可能感兴趣的:(Code记录)