vijosP1447 开关灯泡

来源:互联网 发布:周深 身骑白马知乎 编辑:程序博客网 时间:2024/04/29 00:28
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     do79      {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 }

 

0 0
原创粉丝点击