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];
    
  • 相关阅读:
    数组相关常见的三种错误
    JMeter连接MYSQL数据库并进行操作详解
    JMeter实现动态关联——两个接口在不同的线程组
    Android : kernel中添加虚拟文件节点
    Android O : 系统原生锁屏密码位数限制及自动检查
    Android O : DNS列表获取及IPv4/IPv6优先级修改
    Android 打印调用栈的方法
    Android TV : 系统分区配置及增加私有分区
    Android TV : Mstar平台Audio Path及声音曲线配置
    Android TV : Mstar平台 GPIO 调试
  • 原文地址:https://www.cnblogs.com/Patt/p/4743565.html
Copyright © 2011-2022 走看看