JZOJ 4.8 2434——开关灯泡【高精度】

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.
原文地址:https://www.cnblogs.com/Comfortable/p/8412325.html