vijosP1447 开关灯泡

vijosP1447 开关灯泡

链接:https://vijos.org/p/1447

【思路】

  数学+高精度。

  分析题目:题中有言,i时刻将其所有倍数的灯熄灭,由此得知一个数有多少个倍数就会被操作多少次,因为初始全部熄灭,所以操作数为奇的灯最后会亮着,再进一步,只有序号为平方数的灯在最后会亮着。

  由此题目转化为求n以内平方数的个数,个数为sqrt(n)个(别问我怎么知道的=_=)

  数据范围要求我们用到高精。至此,题目就是对一个大数开方的问题,NOIP的初赛曾出现过这个程序。

【代码】

  

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cmath>
 4 using namespace std;
 5 
 6 const int maxn = 200+10;
 7 struct Bign{
 8     int len;
 9     int num[maxn];
10     Bign() {  memset(num,0,sizeof(num)); }
11 };
12 
13 Bign goal;
14 
15 Bign times(Bign a,Bign b) {
16     Bign c;
17     c.len=a.len+b.len+2;
18     for(int i=0;i<a.len;i++)
19       for(int j=0;j<b.len;j++)
20         c.num[i+j] += a.num[i]*b.num[j];
21     for(int i=0;i<c.len-1;i++) {
22         c.num[i+1] += c.num[i]/10;
23         c.num[i] %= 10;
24     }
25     while(c.num[c.len-1]==0) c.len--;
26     return c;
27 }
28 
29 Bign average(Bign a,Bign b) {
30     Bign c; c.len=max(a.len,b.len);
31     for(int i=0;i<c.len;i++) {
32         c.num[i] += a.num[i]+b.num[i];
33         c.num[i+1] += c.num[i]/10;
34         c.num[i] %= 10;
35     }
36     
37     if(c.num[c.len]) c.len++;
38     for(int i=c.len-1;i;i--) {
39         c.num[i-1] += (c.num[i]%2) *10;
40         c.num[i] /= 2;
41     }
42     c.num[0]/=2;
43     if(c.num[c.len-1]==0) c.len--;
44     return c;
45 }
46 
47 Bign plustwo(Bign a) {
48     a.num[0] += 2;
49     int i=0;
50     while(i<a.len && a.num[i]>=10) {
51         a.num[i+1] += a.num[i]/10;
52         a.num[i] %= 10;
53         i++;
54     }
55     if(a.num[a.len]) a.len++;
56     return a;
57 }
58 
59 bool over(Bign a,Bign b) {
60     if(a.len>b.len) return true;
61     else if(a.len<b.len) return false;
62     
63     for(int i=a.len;i>=0;i--) //倒序 
64       if(a.num[i]>b.num[i]) return true;
65       else if(a.num[i]<b.num[i]) return false;
66     
67     return false;
68 }
69 
70 int main() {
71     ios::sync_with_stdio(false);
72     string s;
73     cin>>s;
74     goal.len=s.size();
75     for(int i=0;i<goal.len;i++) goal.num[i]=s[goal.len-1-i]-'0';
76     Bign L , R=goal , M;
77     L.len=1; L.num[0]=1;
78     do
79      {
80            M=average(L,R);
81            if(over(times(M,M),goal)) R=M;
82            else L=M;
83     } while(! over(plustwo(L),R)) ;
84     for(int i=L.len-1;i>=0;i--) cout<<L.num[i];
85     return 0;
86 }
原文地址:https://www.cnblogs.com/lidaxin/p/4871228.html