zoukankan      html  css  js  c++  java
  • uvalive 6300 Signed Binary Representation of Integers

    6300 Signed Binary Representation of Integers
    Computing a
    x mod n for large integers x and n is the most time-consuming process in most public-key
    cryptography systems. An algorithm to compute a
    x mod n can be described in a C-like pseudo-code as
    follows.
    Input: positive integers a, x and n,
    Output: y = a
    x mod n
    Method:
    convert x into binary (xk−1xk−2 . . . x0)2;
    y = 1;
    for (i = k − 1;i ≥ 0;i = i − 1) {
    y = y
    2 mod n;
    if (xi == 1)y = y × a mod n;
    }
    print y;
    In the above algorithm, first x is converted into k-bit binary. Then the algorithm performs k
    iterations. In each iteration, a square (y
    2 mod n) is computed. In the i-th iteration, if xi = 1, the
    algorithm also computes y = y × a mod n. Therefore, the computing time depends on the number of
    1’s in the binary representation of x.
    Let a
    −1 be the inverse of a in the group Z

    n
    . That is a × a
    −1 ≡ 1 mod n. For example, assume that
    n = 13, then the inverse of 2 is 7, 2 × 7 = 14 ≡ 1(mod13). In this problem, you do not need to know
    how to compute the inverses.
    Assume that a
    −1
    is known, and x is represented by -1, 0, 1, instead of 0, 1, we can modify the above
    algorithm as follows.
    Input: positive integers a, x and n,
    Output: y = a
    x mod n
    Method:
    convert x into signed binary (xk−1xk−2 . . . x0)−1,0,1;
    y = 1;
    for (i = k − 1;i ≥ 0;i = i − 1) {
    y = y
    2 mod n;
    if (xi == 1)y = y × a mod n;
    if (xi == −1)y = y × a
    −1 mod n;
    }
    print y;
    In the above algorithm, we need to represent x by using -1, 0, 1. This is called signed binary
    representation of x. For convenience, we shall use 1 to denote -1. For example: 15 = (1111)2 =
    (10001)−1,0,1.
    You can see that it may be more efficient to use signed binary representation in computing a
    x mod n
    when the inverse of a (a
    −1 mod n) is known. For x = 15, using binary needs 4 multiplications, while
    using signed binary needs only 2.ACM-ICPC Live Archive: 6300 – Signed Binary Representation of Integers 2/2
    In this problem, you are going to write a program to convert a large integer into signed binary.
    Signed binary representation of an integer may not be unique. We need a representation with minimum
    number of non-zero bits to make the computation of a
    x mod n fast.
    A hint of converting x into a signed binary with minimum number of non-zero bits: Make sure that
    no adjacent two bits are both non-zero.
    Input
    The input to this problem is a sequence of large integers. Each integer x is no more than 120 decimal
    digits, and it is written in a line. There will be no spaces in front of x, and no spaces after x. The last
    line of the input file contains a single ‘0’. You do not need to process this line.
    Output
    The outputs for each test case consists of two parts written in one line. The first part is an integer b,
    which is the number of non-zero bits of the binary representation of x. The second part is an integer s,
    which is the number of non-zero bits in the signed binary representation of x. Print exactly one space
    between these two parts.
    Sample Input
    15
    2514593
    113113561845
    0
    Sample Output
    4 2
    11 9
    23 14

    思路:假如是 111 那么就可以转成 100(-1),对于连续的k(k>=2)个1,我们也可以像那么转化。

    每次转化可以减少 k-2个非0

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<cstring>
    #include<set>
    #include<stack>
    #include<string>
    #include<ctime>
    #define LL long long
    #define u64 unsigned long long
    #define maxn 100010
    #define INF 0x3f3f3f3f
    #define eps 1e-6
    using namespace std;
    #define MAXN 9999
    #define MAXSIZE 1000
    #define DLEN 4
    
    class BigNum
    {
    private:
        int a[MAXSIZE];    //可以控制大数的位数
        int len;       //大数长度
    public:
        BigNum(){ len = 1;memset(a,0,sizeof(a)); }   //构造函数
        BigNum(const int);       //将一个int类型的变量转化为大数
        BigNum(const char*);     //将一个字符串类型的变量转化为大数
        BigNum(const BigNum &);  //拷贝构造函数
        BigNum &operator=(const BigNum &);   //重载赋值运算符,大数之间进行赋值运算
    
        friend istream& operator>>(istream&,  BigNum&);   //重载输入运算符
        friend ostream& operator<<(ostream&,  BigNum&);   //重载输出运算符
    
        BigNum operator+(const BigNum &) const;   //重载加法运算符,两个大数之间的相加运算
        BigNum operator-(const BigNum &) const;   //重载减法运算符,两个大数之间的相减运算
        BigNum operator*(const BigNum &) const;   //重载乘法运算符,两个大数之间的相乘运算
        BigNum operator/(const int   &) const;    //重载除法运算符,大数对一个整数进行相除运算
    
        BigNum operator^(const int  &) const;    //大数的n次方运算
        int    operator%(const int  &) const;    //大数对一个int类型的变量进行取模运算
        bool   operator>(const BigNum & T)const;   //大数和另一个大数的大小比较
        bool   operator>(const int & t)const;      //大数和一个int类型的变量的大小比较
    
        void print();       //输出大数
    };
    BigNum::BigNum(const int b)     //将一个int类型的变量转化为大数
    {
        int c,d = b;
        len = 0;
        memset(a,0,sizeof(a));
        while(d > MAXN)
        {
            c = d - (d / (MAXN + 1)) * (MAXN + 1);
            d = d / (MAXN + 1);
            a[len++] = c;
        }
        a[len++] = d;
    }
    BigNum::BigNum(const char*s)     //将一个字符串类型的变量转化为大数
    {
        int t,k,index,l,i;
        memset(a,0,sizeof(a));
        l=strlen(s);
        len=l/DLEN;
        if(l%DLEN)
            len++;
        index=0;
        for(i=l-1;i>=0;i-=DLEN)
        {
            t=0;
            k=i-DLEN+1;
            if(k<0)
                k=0;
            for(int j=k;j<=i;j++)
                t=t*10+s[j]-'0';
            a[index++]=t;
        }
    }
    BigNum::BigNum(const BigNum & T) : len(T.len)  //拷贝构造函数
    {
        int i;
        memset(a,0,sizeof(a));
        for(i = 0 ; i < len ; i++)
            a[i] = T.a[i];
    }
    BigNum & BigNum::operator=(const BigNum & n)   //重载赋值运算符,大数之间进行赋值运算
    {
        int i;
        len = n.len;
        memset(a,0,sizeof(a));
        for(i = 0 ; i < len ; i++)
            a[i] = n.a[i];
        return *this;
    }
    istream& operator>>(istream & in,  BigNum & b)   //重载输入运算符
    {
        char ch[MAXSIZE*4];
        int i = -1;
        in>>ch;
        int l=strlen(ch);
        int count=0,sum=0;
        for(i=l-1;i>=0;)
        {
            sum = 0;
            int t=1;
            for(int j=0;j<4&&i>=0;j++,i--,t*=10)
            {
                sum+=(ch[i]-'0')*t;
            }
            b.a[count]=sum;
            count++;
        }
        b.len =count++;
        return in;
    
    }
    
    BigNum BigNum::operator+(const BigNum & T) const   //两个大数之间的相加运算
    {
        BigNum t(*this);
        int i,big;      //位数
        big = T.len > len ? T.len : len;
        for(i = 0 ; i < big ; i++)
        {
            t.a[i] +=T.a[i];
            if(t.a[i] > MAXN)
            {
                t.a[i + 1]++;
                t.a[i] -=MAXN+1;
            }
        }
        if(t.a[big] != 0)
            t.len = big + 1;
        else
            t.len = big;
        return t;
    }
    BigNum BigNum::operator-(const BigNum & T) const   //两个大数之间的相减运算
    {
        int i,j,big;
        bool flag;
        BigNum t1,t2;
        if(*this>T)
        {
            t1=*this;
            t2=T;
            flag=0;
        }
        else
        {
            t1=T;
            t2=*this;
            flag=1;
        }
        big=t1.len;
        for(i = 0 ; i < big ; i++)
        {
            if(t1.a[i] < t2.a[i])
            {
                j = i + 1;
                while(t1.a[j] == 0)
                    j++;
                t1.a[j--]--;
                while(j > i)
                    t1.a[j--] += MAXN;
                t1.a[i] += MAXN + 1 - t2.a[i];
            }
            else
                t1.a[i] -= t2.a[i];
        }
        t1.len = big;
        while(t1.a[t1.len - 1] == 0 && t1.len > 1)
        {
            t1.len--;
            big--;
        }
        if(flag)
            t1.a[big-1]=0-t1.a[big-1];
        return t1;
    }
    
    BigNum BigNum::operator*(const BigNum & T) const   //两个大数之间的相乘运算
    {
        BigNum ret;
        int i,j,up;
        int temp,temp1;
        for(i = 0 ; i < len ; i++)
        {
            up = 0;
            for(j = 0 ; j < T.len ; j++)
            {
                temp = a[i] * T.a[j] + ret.a[i + j] + up;
                if(temp > MAXN)
                {
                    temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
                    up = temp / (MAXN + 1);
                    ret.a[i + j] = temp1;
                }
                else
                {
                    up = 0;
                    ret.a[i + j] = temp;
                }
            }
            if(up != 0)
                ret.a[i + j] = up;
        }
        ret.len = i + j;
        while(ret.a[ret.len - 1] == 0 && ret.len > 1)
            ret.len--;
        return ret;
    }
    BigNum BigNum::operator/(const int & b) const   //大数对一个整数进行相除运算
    {
        BigNum ret;
        int i,down = 0;
        for(i = len - 1 ; i >= 0 ; i--)
        {
            ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
            down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
        }
        ret.len = len;
        while(ret.a[ret.len - 1] == 0 && ret.len > 1)
            ret.len--;
        return ret;
    }
    int BigNum::operator %(const int & b) const    //大数对一个int类型的变量进行取模运算
    {
        int i,d=0;
        for (i = len-1; i>=0; i--)
        {
            d = ((d * (MAXN+1))% b + a[i])% b;
        }
        return d;
    }
    BigNum BigNum::operator^(const int & n) const    //大数的n次方运算
    {
        BigNum t,ret(1);
        int i;
        if(n<0)
            exit(-1);
        if(n==0)
            return 1;
        if(n==1)
            return *this;
        int m=n;
        while(m>1)
        {
            t=*this;
            for( i=1;i<<1<=m;i<<=1)
            {
                t=t*t;
            }
            m-=i;
            ret=ret*t;
            if(m==1)
                ret=ret*(*this);
        }
        return ret;
    }
    bool BigNum::operator>(const BigNum & T) const   //大数和另一个大数的大小比较
    {
        int ln;
        if(len > T.len)
            return true;
        else if(len == T.len)
        {
            ln = len - 1;
            while(ln >= 0&&a[ln] == T.a[ln])
                ln--;
            if(ln >= 0 && a[ln] > T.a[ln])
                return true;
            else
                return false;
        }
        else
            return false;
    }
    bool BigNum::operator >(const int & t) const    //大数和一个int类型的变量的大小比较
    {
        BigNum b(t);
        return *this>b;
    }
    
    void BigNum::print()    //输出大数
    {
        int i;
        printf("%d",a[len-1]);
        for(i = len - 2 ; i >= 0 ; i--)
        {
            printf("%04d",a[i]);
        }
        //cout << endl;
        printf("
    ");
    }
    int bit[1000010] ;
    char s[210] ;
    
    void solve(int n,int ans)
    {
        int j,i,v;
        i=0;j=n-1;
        while(i<j)
        {
            swap(bit[i],bit[j]) ;
            i++;j--;
        }
        bit[n]=0;
        for( i = 0 ; i < n ;i++)if(bit[i]&&bit[i+1])
        {
            j=i+2;
            while(j<n && bit[j])
            {
                j++ ;
            }
            v=j-i ;
            ans -= v-2;
            if(j != n)bit[j]=1;
            i=j-1;
        }
        cout << ans << endl;
    }
    int main()
    {
        BigNum a ;
        int i,j,k,n,m;
        int len ,ans;
        while(scanf("%s",s) != EOF)
        {
            n = strlen(s) ;
            if(n==1&&s[0]=='0') break ;
            a=BigNum(s) ;
           // a.print();
            len=ans=0;
            while(a>0)
            {
                if(a%2==1) bit[len++] =1,ans++;
                else bit[len++]=0;
                a = a/2;
            }
            printf("%d ",ans) ;
            solve(len,ans) ;
        }
        return 0 ;
    }
    View Code
  • 相关阅读:
    nexus下载远程maven中央仓库的解决方案
    commons-logging 与log4j的关系
    maven设置代理服务器或者镜像服务器
    start with connect by prior 递归查询用法
    想成为马斯克一样创新钢铁侠?首先要学会他的学习方法
    mybatis 一对多,多对一配置
    17款工具,让你的数据更美观
    java spring事务管理相关
    PL/SQL链接Oracle数据库 导出表结构和表数据
    ORACLE创建表空间和用户,并分配权限
  • 原文地址:https://www.cnblogs.com/20120125llcai/p/4354947.html
Copyright © 2011-2022 走看看