sgu111:Very simple problem

可能是我太弱...二分过不了...
这里讲一下另一个思路:
我们可以确定答案的位数,如果数N有奇数位,则答案位数为N/2+1,否则为N/2;
从位数L到1枚举每一位的数字;
枚举有个优化,设已枚举出的k-1位数为T(后接L-k+1个0),对于新枚举出的第k位数t,
设T'=T+t*10^(L-k),由于高精度乘法消耗太大,我们可以由T来推出T'^2;
T'^2=[T+t*10^(L-k)]^2=T^2+2Tt*10^(L-k)+t^2*10^2(L-k);
T^2可以在上次运算中得出,2Tt*10^(L-k)可以先计算出2Tt(高精度×单精度),再把答案扩大10^(L-k)倍;先计算出t^2(同样是高精度×单精度),再把答案扩大10^2(L-k)倍;
T'^2就求出来了,以此类推……

这样就不存在高精度乘高精度导致TLE的问题了。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXL = 1005;

struct BI
{
  short int num[MAXL];
  int len;	
  void print()
  {
    for(int i = len; i >= 1; --i)
	  printf("%d", num[i]);	
  }
}big, ans, tmp;

BI operator + (BI A, BI B)
{
  BI temp = {0};
  int l = max(A.len, B.len);
  for(int i = 1; i <= l; ++i)
  {
    temp.num[i] += A.num[i] + B.num[i];
    temp.num[i + 1] += temp.num[i] / 10;
    temp.num[i] %= 10;
  }
  if(temp.num[l + 1] > 0) temp.len = l + 1;
  else temp.len = l;
  return temp;
}

BI operator * (BI A, BI B)
{
  BI temp[10] = {0}, re = {0};
  temp[0].len = 1;
  for(int i = 1; i <= 9; ++i)
    temp[i] = A + temp[i - 1];
  for(int i = 1; i <= B.len; ++i)
    for(int j = 1; j <= temp[B.num[i]].len; ++j)
	  re.num[i + j - 1] += temp[B.num[i]].num[j]; 
  for(int i = 1; i < A.len + B.len; ++i)
  {
    re.num[i + 1] += re.num[i] / 10;
    re.num[i] %= 10;
  }
  if(re.num[A.len + B.len] > 0) re.len = A.len + B.len;
  else re.len = A.len + B.len - 1;
  return re;
}

BI operator - (BI A, BI B)
{
  for(int i = 1; i <= B.len; ++i)
    A.num[i] -= B.num[i];
  for(int i = 1; i <= A.len; ++i)
  {
    while(A.num[i] < 0) 
    {
      A.num[i] += 10;
	  A.num[i + 1] -= 1;	
    } 
  }
  for(int i = A.len; i >= 1; --i)
    if(A.num[i])
    {
      A.len = i;
	  break;	
    }
  return A;
}

bool operator <= (const BI& A, const BI& B)
{
  if(A.len < B.len) return true;
  else if(A.len > B.len) return false;
  for(int i = A.len; i >= 1; --i)
    if(A.num[i] < B.num[i]) return true;
    else if(A.num[i] > B.num[i]) return false;
  return true;
}


bool flag = false;

void calc(BI ans, BI src)
{
  BI op = {{0}, 1}, last = {{0}, 1}, op1 = {{0}, 1};
  BI t2 = {{0, 2}, 1}, t1 = {{0, 1}, 1};
  for(int i = ans.len; i >= 1; --i)
  {
    int j = 9; 
    for(; j >= ans.num[i]; --j)
	{
	  BI t = {{0, j}, 1};
	  BI tmp = t2 * t * last;
      
      if(i == 5 && j == 0)
        j = 0;

	  //计算2ab 
	  for(int k = tmp.len; k >= 1 && i > 1; --k)
	  {
	    tmp.num[k + i - 1] = tmp.num[k];
	    tmp.num[k] = 0;
	  } 
	  if(tmp.num[i - 1 + tmp.len])  tmp.len = i - 1 + tmp.len;
	  
	  //计算b^2 
	  BI tmp2 = {{0, j}, 1};
	  tmp2 = tmp2 * tmp2;
	  for(int k = tmp2.len; k >= 1 && i > 1; --k)
	  {
	    tmp2.num[k + 2 * (i - 1)] = tmp2.num[k];
	    tmp2.num[k] = 0;
	  }
	  if(tmp2.num[2 * (i - 1) + tmp2.len])  tmp2.len = 2 * (i - 1) + tmp2.len;
	  
	  op = op1 + tmp + tmp2;
	  if(op <= src) break;
    }
    ans.num[i] = j;
    last = ans;
    op1 = op;
  }
  ans.print();
}   

int main()
{
  char c;
  while(scanf("%c", &c) != EOF)
  {
    tmp.num[++tmp.len] = c - '0';	
  }
  big.len = tmp.len;
  for(int i = 1; i <= tmp.len; ++i) big.num[i] = tmp.num[tmp.len - i + 1];
  
  if(big.len & 1)
  {
    memset(ans.num, 0, sizeof(ans.num));
    ans.len = (big.len >> 1) + 1;
    ans.num[ans.len] = 1;
  }
  else 
  {
  	memset(ans.num, 0, sizeof(ans.num));
    ans.len = big.len >> 1;
    ans.num[ans.len] = 1;
  }  
  
  calc(ans, big);
  
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值