蛮力法——狱吏问题
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
题目大意:狱吏问题)某王国对囚犯进行大赦,让一狱吏n次通过一排锁着的n间牢房,每通过一次按所定规则转动门锁,每转动一次,原来锁着的被打开,原来打开的被锁上;通过n次后,门锁开着的,牢房中的犯人放出,否则犯人不得获释.转动门锁的规则是这样的,第一次通过牢房,要转动每一把门锁,即把全部锁打开;第二次通过牢房时,从第二间开始转动,每隔一间转动一次;第k次通过牢房,从第k间开始转动,每隔k-1 间转动一次;问通过n次后,那些牢房的锁仍然是打开的?
三种方法:
所有方法中锁的状态:1代表锁着,0代表开着
1、纯暴力法
C++代码:
#include<iostream>
using namespace std;
int main(){
int n,*prisoner;
cin>>n;
prisoner=new int[n+1];
for(int i=0;i<=n;i++)
prisoner[i]=1;
for(int i=1;i<=n;i++) //i--->表示狱吏是第几轮走过
for(int j=i;j<=n;j=j+i) //j--->需要改变的锁的编号
prisoner[j]=1-prisoner[j];
for(int i=1;i<=n;i++)
if(prisoner[i]==0)
cout<<i<<" ";
return 0;
}
2、利用因子数
C++代码:
//利用因子数的个数得出每个编号的锁中间变换状态的次数
//eg i=4时,它的因子有1,2,4,所以他在第1,2,4轮时会变换状态
#include<iostream>
using namespace std;
int main(){
int n,*prisoner;
cin>>n;
prisoner=new int[n+1];
for(int i=0;i<=n;i++)
prisoner[i]=1;
for(int i=1;i<=n;i++)
{
int count=1;
for(int j=2;j<=i;j++)
if(i%j==0)
count++;
if(count%2==0)
prisoner[i]=1;
else
prisoner[i]=0;
}
for(int i=1;i<=n;i++)
if(prisoner[i]==0)
cout<<i<<" ";
return 0;
}
3、找规律
C++代码:
//利用规律来判断
//规律:当锁的标号为一个数的平方时,那么最后它会开着
eg.(其中1代表锁着,0代表开着)
锁的标号:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
最后状态:0 1 1 0 1 1 1 1 0 1 1 1 1 1 1 0
#include<iostream>
#include<math.h>
using namespace std;
int main(){
int n,*prisoner;
cin>>n;
prisoner=new int[n+1];
for(int i=0;i<=n;i++)
prisoner[i]=1;
for(int i=1;i<=sqrt(n);i++){
int temp=i*i;
if(temp<=n)
prisoner[temp]=0;
}
for(int i=1;i<=n;i++)
if(prisoner[i]==0)
cout<<i<<" ";
return 0;
}
题目大意:狱吏问题)某王国对囚犯进行大赦,让一狱吏n次通过一排锁着的n间牢房,每通过一次按所定规则转动门锁,每转动一次,原来锁着的被打开,原来打开的被锁上;通过n次后,门锁开着的,牢房中的犯人放出,否则犯人不得获释.转动门锁的规则是这样的,第一次通过牢房,要转动每一把门锁,即把全部锁打开;第二次通过牢房时,从第二间开始转动,每隔一间转动一次;第k次通过牢房,从第k间开始转动,每隔k-1 间转动一次;问通过n次后,那些牢房的锁仍然是打开的?