开关灯问题

Description

n盏灯排成一排,从1到n按顺序依次编号。有n个人也从1到n依次编号。第一个人(1号)将灯全部关闭。第二个人(2号)将凡是2和2的倍数的灯打开。第三个人(3号)将凡是3和3的倍数的灯作相反处理(该灯如为打开的将其关闭;如为关闭的,将其打开)。以后的人都和三号一样,将凡是与自己相同的灯和是自己编号倍数的灯作相反处理。请问,当第n个人操作之后,从第A盏灯跟第B盏灯之间(包含AB两盏),有多少灯是开着的?

Input

N,A,B(A<B<N<10^7)

Output

 从A到B(包含AB)开着的灯的数目
Sample Input
 5 1 3
Sample Output
2
解法一:
  初看到这个题,我的思路是从人的角度出发的。即设置两层循环,外循环为灯,内循环为人,每来一个人则将他的序号和序号倍数的灯的状态改变一次(0为关,1为开)。最后再用count记录一下1的个数。但是,在改变灯的状态时,我最开始用的是“~”,但是我忽略了1的二进制前面的0,认为~1=0。后来我用异或代替取反,求解出了答案。代码如下

<span style="font-size:14px;">#include<iostream>
#include<string.h>
int l[10000000] ;
using namespace std;
int main()
{
	int light,n1,n2,count=0;
	cin>>light>>n1>>n2;
	memset(l,0,n2);
	for(int i=2;i<=n2;i++)
	{
		for(int j=1;j<=light;j++)
		{
			if(j%i==0)
			{
				l[j]=l[j]^1;
			}
		}
	}
	for(int i=1;i<=n2;i++)
	{
		if(l[i]==1)
			count++;
	}
	cout<<count<<endl;
	return 0;
	
}</span><div>
</div>

但这种方法每来一个人都要判断所有的灯,因此可以用每个人的序号作步长,这样就可以减少判断的次数。

解法二:

从灯的角度来说,如果灯的开关次数是偶数,则最终灯是亮着的,如果是奇数是关着的。我们只需判断灯的因子是奇数还是偶数即可。完全平方数的因子是奇数,题目就简化为了判断灯序号是不是完全平方数了。代码如下

#include<iostream>
#include<math.h>
using namespace std;
int main()
{
	int light,n1,n2,count=0;
	cin>>light>>n1>>n2;
	for(int i=n1;i<=n2;i++)
	{
		int x=(int)sqrt(i);
		if(x*x!=i)
			count++;
	}
	cout<<count<<endl;
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值