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("\n");
}
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
复制代码

 

posted @   _log__  阅读(160)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示