题目描述
首先所有的灯都是关的(注意是关!),编号为1的人走过来,把是一的倍数的灯全部打开,编号为二的的把是二的倍数的灯全部关上,编号为3的人又把是三的倍数的灯开的关上,关的开起来……直到第N个人为止。
给定N,求N轮之后,还有哪几盏是开着的。
输入格式
一个数N,表示灯的个数和操作的轮数
输出格式
若干数,表示开着的电灯编号
输入输出样例
输入
5
输出
1 4
说明/提示
1 < = N < = 2 4 0 1<=N<=2^40 1<=N<=240(数学题)
看到这道题没点奥数知识还真有点一头雾水,(暴力模拟啊),显然一个灯开着就代表着它被开了奇数次。
那我们考虑,能开这个灯的只有当前灯序号
i
i
i的因数
a
a
a,而因数显然能被i整除出来一个数
b
=
i
/
a
b = i/a
b=i/a,那么相同的,
b
b
b也是
i
i
i的因数,所以因数一般都是成对出现的。
那么因数怎么才能不成对出现呢?,那就是当
a
=
b
a = b
a=b时,这个因数就单独出现的,那么
i
i
i的因数就变为了奇数。
同时很显然的是当因数
a
=
i
a
=
b
a = \frac{i}{a} = b
a=ai=b时a就是
i
\sqrt{i}
i
而如果一个数
i
=
a
∗
a
i = a * a
i=a∗a那么这个数就是完全平方数,那么显然符合条件的数就是n以内的完全平方数,我们暴力枚举输出就行了。
#include<bits/stdc++.h>
#define ll long long
#define rg register
using namespace std;
ll n;
int main()
{
scanf("%lld", &n);
for(rg ll i = 1; i * i <= n; ++i){
printf("%lld ", i * i);
}puts("");
return 0;
}