湖南省第八届大学生计算机程序设计竞赛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
50
解题思路:二分法(对于二进制,其实就是0、1枚举法)。用bitset来储存二进制小数,用二分法算出x2-a=0的解。然后字符串匹配即可。C++语言代码如下:
#include <cstdio> #include <cstdlib> #include <string> #include <cmath> #include <bitset> using namespace std; #define MAX_LENGTH 2250 #define DECIMAL_DIGITS 1000 #define FAC_MAX_LENGTH 150 #define FAC_DECIMAL_DIGITS 100 typedef bitset <MAX_LENGTH> BigInt; typedef bitset <FAC_MAX_LENGTH> FacBigInt; BigInt operator+ ( const BigInt & a, const BigInt & b ) { BigInt result; result.reset( ); int temp; int carry = 0; for ( int i = MAX_LENGTH - 1; i >= 0 ; i -- ) { temp = a[i] + b[i] + carry; carry = (temp >> 1); result[i] = (temp & 1); } return result; } BigInt & operator+= ( BigInt & a, const BigInt & b ) { int temp; int carry = 0; for ( int i = 0; i < MAX_LENGTH ; i ++ ) { temp = a[i] + b[i] + carry; carry = (temp >> 1); a[i] = (temp & 1); } return a; } bool operator> ( const BigInt & a, const BigInt & b ) { for ( int i = MAX_LENGTH - 1 ; i >= 0 ; i -- ) { if ( a[i] > b[i] ) return true; else if ( a[i] < b[i] ) return false; } return false; } inline BigInt FacBigIntToBigInt( const FacBigInt & n ) { return BigInt(n.to_string()) << ( DECIMAL_DIGITS - FAC_DECIMAL_DIGITS ); } BigInt & GetSq( const FacBigInt & n ) { static BigInt result; result.reset( ); BigInt m = FacBigIntToBigInt(n); for ( int i = DECIMAL_DIGITS - FAC_DECIMAL_DIGITS ; i < FAC_MAX_LENGTH + DECIMAL_DIGITS - FAC_DECIMAL_DIGITS ; i ++ ) { if ( m[i] ) result += ( m << i ); } result >>= DECIMAL_DIGITS; return result; } FacBigInt & GetSqrt( const unsigned long input ) { static FacBigInt mid; BigInt radicand = BigInt (input); BigInt square; radicand <<= DECIMAL_DIGITS; unsigned long intPart = static_cast<unsigned long>(sqrt(input)); mid = intPart; mid <<= FAC_DECIMAL_DIGITS; if ( ( square = GetSq(mid) ) == radicand ) return mid; for ( int i = FAC_DECIMAL_DIGITS - 1 ; i >= 0 ; i -- ) { mid[i] = 1; if ( ( square = GetSq(mid) ) == radicand ) break; else if ( square > radicand ) mid[i] = 0; } return mid; } int main ( ) { int test_cases; unsigned long input; char find_string[105]; FacBigInt root; scanf( "%d", &test_cases ); while ( test_cases -- ) { scanf( "%lu", &input ); root = GetSqrt( input ); scanf( "%s", find_string ); int pos = root.to_string().find(string(find_string), FAC_MAX_LENGTH - FAC_DECIMAL_DIGITS ) - (FAC_MAX_LENGTH - FAC_DECIMAL_DIGITS); printf( "%d\n", pos ); } return EXIT_SUCCESS; }