Description
在二进制中,2的算术平方根,即sqrt(2),是一个无限小数1.0110101000001001111...
给定一个整数n和一个01串S,你的任务是在sqrt(n)的小数部分(即小数点之后的部分)中找到S第一次出现的位置。如果sqrt(n)是整数,小数部分看作是无限多个0组成的序列。
Input
输入第一行为数据组数T (T<=20)。以下每行为一组数据,仅包含一个整数n (2<=n<=1,000,000)和一个长度不超过20的非空01串S。
Output
对于每组数据,输出S的第一次出现中,第一个字符的位置。小数点后的第一个数字的位置为0。输入保证答案不超过100。
Sample Input
2 2 101 1202 110011
Sample Output
2 58
题解: 求出二进制小数点后120左右,在查找s串在ans串的位置就可以了。二进制小数位转换成十进制的方法是0或者1乘上2的(-n)次方,反过来是*2取整。然后不断逼近n就可以求出小数位120位了。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cmath>
using namespace std;
int a1[10010],a2[10010],b[10000],c[10000],l1,l2,s[110000];
int l3,l4,l5,point,point2,point3,point1;
char ans[1000];
char ss[23];
int chengfa()
{
int pos,i,j;
memset(s,0,sizeof(s));
for (i=1;i<=l4;i++)
for (j=1,pos=i;j<=l4;j++)
s[pos++]+=a2[i]*a2[j];
pos-=1;
for (i=1;i<=pos;i++)
if (s[i]>=10)
{
if (i==pos) pos++;
s[i+1]+=s[i]/10;
s[i]%=10;
}
return pos;
}
void jia()
{
int p=1,i;
if (point > point1)
{
for (i=1;i<=point - point1;i++)
a2[p++]=a1[i];
int tt=1;
for (i=point - point1+1;i<=l1;i++)
a2[p++]=a1[i]+c[tt++];
point2=point;
}
else
{
for (i=1;i<=point1-point;i++)
a2[p++]=c[i];
int tt=i;
for (i=1;i<=l1;i++)
a2[p++]=a1[i]+c[tt++];
point2=point1;
}
int kk=0;
p--;
for (i=1;i<=p;i++)
{
a2[i]+=kk;
kk=a2[i]/10;
a2[i]%=10;
}
if (kk!=0) a2[++p]=kk;
l4=p;
}
int gobj()
{
int sl=l5,bl=l2;
if (sl-point3>bl) return 1;
else if (sl-point3<bl) return -1;
while (sl>0 && bl>0)
{
if (s[sl]>b[bl]) return 1;
if (s[sl]<b[bl]) return -1;
sl--;bl--;
}
if (sl==0) return 0;
else return 1;
}
int main()
{
int T,n;
scanf("%d",&T);
while (T--)
{
memset(ans,0,sizeof(ans));
memset(a1,0,sizeof(a1));
memset(a2,0,sizeof(a2));
memset(c,0,sizeof(c));
memset(b,0,sizeof(b));
scanf("%d",&n);
getchar();
scanf("%s",&ss);
int m=sqrt(n);
int mm=m;
int j=1;
l1=0;
point=0;
while (mm)
{
a1[j++]=mm % 10;
mm/=10;
l1++;
}
point=0;
mm=n;
j=1;l2=0;
while (mm)
{
b[j++]=mm%10;
mm/=10;
l2++;
}
c[1]=1;l3=1;
int i;
for (i=1;i<=130;i++)
{
for (j=1;j<=l3;j++)
c[j]*=5;
int kk=0;
for (j=1;j<=l3;j++)
{
c[j]+=kk;
kk=c[j]/10;
c[j]=c[j]%10;
}
if (kk) c[++l3]=kk;
point1=i;
jia();
/*for (j=l4;j>0;j--)
{
if (point2==j) cout<<".";
printf("%d",a2[j]);
}
cout<<endl;*/
l5=chengfa(); //平方后长度
point3=2*point2; //平方后小数点位置
/*for (j=l5;j>0;j--)
{
if (point3==j) cout<<".";
printf("%d",s[j]);
}
cout<<endl;*/
int re=gobj();
if (re==1) //1:s>b -1:s<b
ans[i-1]='0';
else if (re==-1)
{
ans[i-1]='1';
memset(a1,0,sizeof(a1));
for (j=1;j<=l4;j++)
a1[j]=a2[j];
l1=l4;
point=point2;
}
else break;
}
for (j=i;j<=130;j++)
ans[i]='0';
ans[130]='\0';
//cout<<ans<<endl;
cout<<strstr(ans,ss) - ans << endl;
}
return 0;
}