湖南省第八届程序设计竞赛D

 

题目D. 平方根大搜索

 

在二进制中,2的算术平方根,即sqrt(2),是一个无限小数1.0110101000001001111...

 

给定一个整数n和一个01串S,你的任务是在sqrt(n)的小数部分(即小数点之后的部分)中找到S第一次出现的位置。如果sqrt(n)是整数,小数部分看作是无限多个0组成的序列。

 

输入格式

输入第一行为数据组数T (T<=20)。以下每行为一组数据,仅包含一个整数n (2<=n<=1,000,000)和一个长度不超过20的非空01串S。

 

输出格式

对于每组数据,输出S的第一次出现中,第一个字符的位置。小数点后的第一个数字的位置为0。输入保证答案不超过100。

 

样例输入                                    样例输出

2

2 101

1202 110011

2

58

代码:

// Yiming Li
#include<cstdio>
#include<cstring>
#include<cassert>
using namespace std;

char s[1000];
int a[1000];
int rem[1000];
int b[1000];

int main()
{
  int i,j,n,l,t,b1;
  scanf("%d",&t);
  assert(t<=100);
  for (l=0;l<t;l++)
  {
    scanf("%d%s",&n,s);
    assert(2<=n && n<=1000000 && strlen(s)<=20);
    memset(a,0,sizeof(a));
    for (i=19;i>=0;i--)
      if (n>=(1<<i))
      {
        n-=(1<<i);
        a[i+280]=1;
      }
    memcpy(rem,a,sizeof(a));
    for (i=149;i>=0;i--)
    {
      b1=0;
      for (j=299;j>149+i+1;j--)
        if (rem[j]==1)
        {
          b1=1;break;
        }
      if (b1==0)
      {
        for (j=149;j>i;j--)
        {
          if (rem[j+i+1]>b[j])
          {
            b1=1;break;
          }
          if (rem[j+i+1]<b[j])
          {
            b1=-1;break;
          }
        }
      }
      if ((b1==-1)||((b1==0)&&(rem[i+i]==0)&&(rem[i+i+1]==0)))
      {
        b[i]=0;
      }
      else
      {
        b[i]=1;
        for (j=149;j>i;j--)
          rem[j+i+1]-=b[j];
        rem[i+i]--;
        for (j=i+i;j<300;j++)
          if (rem[j]<0)
          {
            rem[j]+=2;
            rem[j+1]--;
          }
      }
    }

    n=strlen(s);
    for (i=139;i>=0;i--)
    {
      b1=1;
      for (j=0;j<n;j++)
        if (b[i-j]!=s[j]-'0') b1=0;
      if (b1==1)
      {
        assert(139-i<=100);
        printf("%d\n",139-i);
        break;
      }
    }
  }
  return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值