swust oj 480 #Locker doors【详解】

题目描述

走廊上有n个储物柜,从1到n依次编号。最初,所有的储物柜门都关闭了。你经过储物柜,每次从储物柜#1开始。在第 i 次传递中,i = 1, 2, ..., n,你切换每个第 i 个储物柜的门:如果门是关闭的,你打开它,如果它是打开的,你关闭它。例如,在第一次通过后,每扇门都打开;第二遍中,您只切换偶数储物柜(#2、#4、...),以便在第二遍后偶数门关闭并打开奇数门;第三次通过你关闭储物柜#3的门(从第一次通过打开),打开储物柜#6的门(从第二次通过关闭),依此类推。在最后一次通过后,哪些储物柜门打开,哪些关闭?其中有多少是开放的? 你的任务是编写一个程序来输出 最后一次通过后打开了多少扇门?假设所有的门一开始都是关闭的

题目意思:有n的储物柜,起初每扇门都是关闭的,在第一次经过的时候打开所有门;第二次经过的时候关闭偶数门,此时开着的只有奇数门;第三次经过的时候对是3的倍数的门的编号进行操作(开着的关闭,关着的打开)依次类推,最后一次即为第n次。

ps:oj题目表述意思真的很迷,我看了很久也没看出来题目中有体现是在第二次操作以后,每个第i次操作只需要对是i的倍数的编号的门进行开关就行.......

输入

a positive numbers n, total doors. n<=100000
(一个正数n,门的总数)

输出

a positive numbers ,the total of doors opened after the last pass.
(一个正数,最后一次通过后打开了多少扇门)

样例输入复制

10

样例输出复制

3

样例分析:

 方法一:如果你继续往后写,发现的规律就是,从1到n的数中开根号为整数的,就是最后一次通过后仍然打开的门的编号。

ps:之前看到过一个评论说的是:如果我们把每扇门的位置当成一个数,那么这道题就是求每个数的因数个数,如果它的因数个数是奇数个,那么最终这扇门就是开着的(与初始门的状态相反),反之,如果这扇门因数个数是偶数个,那么这扇门最终就是关着的。而函数表达的比输入数小的奇数和(通过等差数列求和公式你会发现就是判断一个数是否为平方数)。而一个数的因数是奇数个,那么这个数就一定是平方数。因此可用此方法.

具体代码如下:

#include<iostream>
#include<math.h>
using namespace std;
int main() {
	int n;
	cin >> n;
	int cnt = 0;
	for (int i = 1; i <=sqrt(n); i++) {
		if (i * i <= n)cnt++;
	}
	cout << cnt << endl;
}

方法二:

如果没有发现上述规律,也可以用遍历来写。(思路还是简单的,循环实现就行,代码我还没写,先欠着。。。。。。)

两个for循环,第一层是次数,第二层就是每次对1-n的数进行判断,用数组存,如果是i的倍数且小于等于n就标记为1,即是打开。循环到最后一次。再来一个for循环,数组为1的就cnt++.时间复杂度是O(n2)比较高。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值