题目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;
}