Description
一个房间里有n盏灯泡,一开始都是熄着的,有1到n个时刻,每个时刻i,我们会将i的倍数的灯泡改变状态(即原本开着的现将它熄灭,原本熄灭的现将它点亮),问最后有多少盏灯泡是亮着的。
Input
一个数n
Output
m,表示最后有m盏是亮着的
Sample Input
5
Sample Output
2
Hint
范围:40%的数据保证,n<=maxlongint
100%的数据保证,n<=10^200
1 ———还剩一盏灯
2 3 4 ————还剩两盏灯
5 6 7 8 9 ————还剩三盏灯
10 11 12 13 14 15 16 ————还剩四盏灯
……
……
由这个规律,我们看出其实这题只是将n 开方就得出解。那我们怎么得出解呢?
分析:
其实n最长为200位,所以我们枚举长度,最多枚举到100位,所以我们就可以用枚举被开方后的数。
我们可以举个例子:
如:124860 为一个6位数,则被开方的数为3位数
那我们就可以从高位开始枚举9~0,一直枚举到这个数小于n。
(Tips:这题要用到高精度乘高精度)
代码如下:
var
a,b,c:array[0..300] of longint;
n:longint;
procedure init;
var
i:longint;
s:string;
begin
readln(s);
n:=length(s);
for i:=1 to n do c[300-(n-i)]:=ord(s[i])-48;
end;
procedure main;
var
i,j,k,z:longint;
flag:boolean;
begin
for i:=300-n div 2 to 300 do
begin
for j:=9 downto 0 do
begin
a[i]:=j;
fillchar(b,sizeof(b),0);
for k:=200 to 300 do
for z:=200 to 300 do
b[k+z-300]:=b[k+z-300]+a[k]*a[z];
for k:=300 downto 1 do
begin
b[k-1]:=b[k-1]+b[k] div 10;
b[k]:=b[k] mod 10;
end;
flag:=true;
for k:=0 to 300 do if b[k]<>c[k] then break;
if b[k]>c[k] then flag:=false;
if flag=true then break;
end;
end;
end;
procedure print;
var
i,j:longint;
begin
for i:=0 to 300 do if a[i]<>0 then break;
for j:=i to 300 do write(a[j]);
end;
begin
init;
main;
print;
end.