UVA 12505 湖南省第八届大学生程序设计大赛原题 D - 平方根大搜索

D - 平方根大搜索

Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu

Submit Status Practice CSU 1114

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 

题意:将一个数开平方,得到小数部分和给定的字符串比较,输出相应的第一个位置分析:double存不下100位的精度,只有用模拟。题目太难,看解题报告理解了好久,下面是标程,加上了自己理解的注释,可能写的比较乱,表达不是很好,还望见谅
#include<cstdio>
#include<cstring>
const int maxn=1111;
char s[maxn];
int a[maxn],b[maxn],res[maxn];
int main(){
    int t,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d%s",&n,s);
        memset(a,0,sizeof a);
        //将n分解成二进制,保存到a[280]->a[299];
        for(int i=19;i>=0;i--){
            if(n>=(1<<i)){
                n-=(1<<i);
                a[i+280]=1;
            }
        }
        memcpy(res,a,sizeof(a));//为什么要复制?多此一举的开了一个a数组
        for(int i=149;i>=0;i--){
            int b1=0;//标记
            /*为什么这里是149,而后面是139?因为前十位存的是整数部分!n化成二进制最多要20位,开埂号后最后为10位*/
            for(int j=299;j>149+i+1;j--)//目前查找到的开方数有149-i位,299-(149-i)=150+i;
                if(res[j]==1){
                    /*前面如果某一位为1;当前b[i]必定上1,因为在后面加上一个1,平方后仍然小于原来的数;*/
                    b1=1;break;
                }

            if(b1==0)//如果为0,比较res和b;确保商1的话,得到的平方小于n’;
                for(int j=149;j>i;j--){
                    if(res[j+i+1]>b[j]){
                        b1=1;//一位一位比较,先找到比他大的,说明可以商1,先找到的比它小,那么只能商0
                        break;
                    }
                    if(res[j+i+1]<b[j]){
                        b1=-1;break;
                    }
                }
            //我们这里来看看,00*00=0000,01*01=0001,10*10=0100,11*11=1001;
            //11*11=1001,111*111= 110001,110*110=100100,1111*1111= 11100001,1110*1110=11000100
            //商零,对前面的几位并没有任何影响,最后两位为0,不用修正,
            //商1,最后两位为01,对前面的数有一定的影响,需要修正
            if(b1==-1||b1==0&&res[i+i]==0&&res[i+i+1]==0) b[i]=0;
            /*与b[i]对应的连续的两位都为0的话,b[i]只能上0,上1的话res[i*i]必定为1;*/
            else{
                b[i]=1;//商1,res减去对应位的b,
                for(int j=149;j>i;j--)
                    res[j+i+1]-=b[j];//前面的减b[j],将n逐渐逼向0
                res[i+i]--;//最后一位减1,倒数第二位为0,不需要修正
                //修正res的值,将小于0的位补正
                for(int j=i+1;j<300;j++)
                    if(res[j]<0){
                        /*如果某位小于零,则需要借位,将这一位加2(因为是二进制),下一位减一*/
                        res[j]+=2;
                        res[j+1]--;
                    }
                //修正后的res一定大于0,否则不会商1.如果下次商0,得到的平方不会改变,不用修改res,
                //如果商1,得到的平方必定小于n,将n剪掉b,不停的用二分,将n逼近于0
            }
        }
        n=strlen(s);
        //b中保存的是平方根(倒着保存的,即最后一位是小数点后第一位)
        for(int i=139;i>=0;i--){
            int b1=1;
            for(int j=0;j<n;j++)//对比,完全一样的就输出起始位置
                if(b[i-j]!=s[j]-‘0‘) b1=0;
            if(b1){
                printf("%d\n",139-i);
                break;
            }
        }
    }
    return 0;
}
时间: 2024-11-08 12:32:38

UVA 12505 湖南省第八届大学生程序设计大赛原题 D - 平方根大搜索的相关文章

湖南省第八届大学生程序设计大赛原题 J

J - 病毒 Time Limit:3000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu Submit Status Practice CSU 1120 Description 你有一个日志文件,里面记录着各种系统事件的详细信息.自然的,事件的时间戳按照严格递增顺序排列(不会有两个事件在完全相同的时刻发生). 遗憾的是,你的系统被病毒感染了,日志文件中混入了病毒生成的随机伪事件(但真实事件的相对顺序保持不变).备份的日志

湖南省第八届大学生程序设计大赛原题 E

E - 最短的名字 Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Practice CSU 1115 Description 在一个奇怪的村子中,很多人的名字都很长,比如aaaaa, bbb and abababab. 名 字这么长,叫全名显然起来很不方便.所以村民之间一般只叫名字的前缀.比如叫'aaaaa'的时候可以只叫'aaa',因为没有第二个人名字的前三个字母

湖南省第八届大学生程序设计大赛原题 C

C - Updating a Dictionary Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu Submit Status Practice CSU 1113 Description In this problem, a dictionary is collection of key-value pairs, where keys are lower-case letters, and v

湖南省第八届大学生程序设计大赛原题 B

B - 机器人的指令 Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu Submit Status Practice CSU 1112 Description 数轴原点有一个机器人.该机器人将执行一系列指令,你的任务是预测所有指令执行完毕之后它的位置. ·LEFT:往左移动一个单位 ·RIGHT: 往右移动一个单位 ·SAME AS i: 和第i 条执行相同的动作.输入保证i 是一个正整数,且不

湖南省第八届大学生程序设计大赛原题 A

A - 三家人 Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu Submit Status Practice CSU 1111 Description 有 三户人家共拥有一座花园,每户人家的太太均需帮忙整理花园.A 太太工作了5 天,B 太太则工作了4 天,才将花园整理完毕.C 太太因为正身怀六甲无法加入她们的行列,便出了90元.请问这笔钱如何分给A.B 二位太太较为恰当?A 应得多少元?90

最简单的问题(重庆市第八届大学生程序设计大赛D) (线段树+离线思想)

考场上的时候直接一脸懵逼了,啥? 区间里面又要求子区间,还TM有上下界? 略加思索后倒是发现没有那么麻烦,因为很容易得出如下结论: 1.对于一个满足条件的区间[L , R],对于他所有的子区间显然也满足条件. 2.一个区间[L , R]的子区间数量(包括自己)为(R-L+1)*(R-L+2)/2 证:因为区间都是连续的,所以显然该区间含有R-L+1个长度为1的子区间,R-L个长度为2的子区间,R-L-1个长度为3的子区间......1个长度为R-L+1的子区间 然后根据等差数列求和公式 Sn =

山东省第一届ACM大学生程序设计竞赛(原题) 回顾 4.18

Phone Number 题目链接:http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2151&cid=1172 题意很简单:给出N行电话号码,寻找有没有一串是另一串的前缀,有的话输出No,当然两个一样的也是No 题解:没有前缀0,直接用二维数组存,大循环就行了,用strcmp比较相等.不会超时. Hello World!     题目链接:http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=215

CSU OJ 1120 病毒(湖南省第八届大学生计算机程序设计竞赛)

 1120: 病毒 Time Limit: 3 Sec  Memory Limit: 128 MB Submit: 146  Solved: 53 [Submit][Status][Web Board] Description 你有一个日志文件,里面记录着各种系统事件的详细信息.自然的,事件的时间戳按照严格递增顺序排列(不会有两个事件在完全相同的时刻发生). 遗憾的是,你的系统被病毒感染了,日志文件中混入了病毒生成的随机伪事件(但真实事件的相对顺序保持不变).备份的日志文件也被感染了,但由于

CSU OJ 1111 三家人 (湖南省第八届大学生计算机程序设计竞赛)

 1111: 三家人 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 356  Solved: 142 [Submit][Status][Web Board] Description 有三户人家共拥有一座花园,每户人家的太太均需帮忙整理花园.A 太太工作了5 天,B 太太则工作了4 天,才将花园整理完毕.C 太太因为正身怀六甲无法加入她们的行列,便出了90元.请问这笔钱如何分给A.B 二位太太较为恰当?A 应得多少元?90/(5+4)*5=$5