zoukankan      html  css  js  c++  java
  • UVa 12505 Searching in sqrt(n)

    传送门

    一开始在vjudge上看到这题时,标的来源是CSU 1120,第八届湖南省赛D题“平方根大搜索”。今天交题时CSU突然跪了,后来查了一下看哪家OJ还挂了这道题,竟然发现这题是出自UVA的,而且用的原题。


    Description

    time limit 5s

    In binary, the square root of 2, denoted by sqrt(2), is an infinite number 1.0110101000001001111... Given an integer n and a binary string (i.e. a string consisting of 0 and 1) S, your task is to find the first occurrence of S in the fraction part (i.e. the part after the decimal point) of sqrt(n). In case sqrt(n) is an integer, the fraction part is an infinite sequence of zeros.

    Input

    The first line contains T (T ≤ 100), the number of test cases. Each of the following lines contains an integer n (2 ≤ n ≤ 1, 000, 000) and a binary string S with at most 20 characters.

    Output

    For each case, print the position of the first character in the first occurrence of S. The first digit after the dot is at position 0. The answer is guaranteed to be no greater than 100.

    Sample Input

    2

    2 101

    1202 110011

    Sample Output

    2

    58

    Solution

    高精度

    复杂度 $O(n^3)$

     

    #include <bits/stdc++.h>
    using namespace std;
    const int N(300), M(125);
    int get_len(int n){
        if(!n) return 1;
        int res=0;
        for(;n;res++,n>>=1);
        return res;
    }
    void trans(int n, int *bit, int &len){
        int l=get_len(n);
        for(int i=len+l-1; i>=len; i--){
            bit[i]=n&1, n>>=1;
        }
        len+=l;
    }
    int tmp[N], a[N], b[N], len, _len, LEN;
    void sqr(){ //error-prone
        memset(tmp, 0, sizeof(tmp));
        for(int i=0; i<len; i++) for(int j=0; j<len; j++) tmp[i+j]+=a[i]*a[j];
        for(int i=2*len-2; i; i--){
            tmp[i-1]+=tmp[i]/2;
            tmp[i]%=2;
        }
        trans(tmp[0], b, LEN=0);
        for(int i=1; i<=2*len-2; i++) b[LEN++]=tmp[i];
    }
    int get_int(){
        int res=0, l=LEN-2*_len;
        for(int i=l-1, _pow=1; i>=0; res+=b[i]*_pow, i--, _pow<<=1);    //error-prone
        return res;
    }
    int solve(){
        int n; string s, t; cin>>n>>t;
        int m=sqrt(n);
        if(m*m==n) return 0;
        len=_len=0;
        trans(m, a, len);
        int tmp=len;
        while(_len<M){
            a[len++]=1, _len++;
            sqr();
            if(get_int()>=n) a[len-1]=0;
        }
        for(int i=tmp; i<len; i++) s+='0'+a[i]; 
        return s.find(t);
    }
    int main(){
        //freopen("in", "r", stdin);
        int T;
        for(cin>>T; T--; cout<<solve()<<endl);
    }
    

    有意写得短一些,但还是有50行,太长了都不想看~

    总结

    总结一下高精度度乘法的写法,虽说也没什么可总结的。

    无论二进制还是十进制,写法都一样,以下代码结合题目按二进制写。

    1. 大整数的存法:int[]数组,左边高位(左高右低即书写格式,这样处理有一定优越性(真的有优越性吗?)),0-indexed

    2. 将长为n的大整数的a[]和长为m的大整数的b[]相乘

    先按如下方式将长为n+m-1中间结果存在数组tmp[]

    memset(tmp, 0, sizeof(tmp));
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
            tmp[i+j]+=a[i]*b[j];
    

    再处理出最终结果存到数组c[]

    for(int k=i+j-2; k; k--)
        tmp[k-1]+=tmp[k]/2, tmp[k]%=2;
    
    int get_len(int n){
        if(!n) return 1;
        int res=0;
        for(; n; res++, n>>=1);
        return res;
    }
    
    len=get_len(tmp[0]);
    for(int i=len-1; i>=0; i--)
        c[i]=tmp[0]%2, tmp[0]/=2;
    
    for(int k=1; k<i+j-1; k++)
        c[len++]=tmp[k];
    
  • 相关阅读:
    c#隐藏和重写基类方法的区别
    c#事件(续委托之后)
    c# 中接口和抽象类的区别
    call 和apply 的一个记录
    string 和 stringbuilder 的区别
    传值和传引用
    值类型和引用类型
    标签选择器与字体连写
    input表单案例
    codeforces 676B B. Pyramid of Glasses(模拟)
  • 原文地址:https://www.cnblogs.com/Patt/p/4743565.html
Copyright © 2011-2022 走看看