回 帖 发 新 帖 刷新版面

主题:第44次编程比赛第二题~~

算术编码是已知的最接近理论极限的压缩算法~~

下面这题就是仿照其出的~~

s是一个字符串,只由a,b,c三个字符组成,如accb~~

一开始,假设a,b,c再此之前各出现过一次,我们用Na来表示a出现的次数,b,c同,则Na=1,Nb=1,Nc=1, 用Pa表示a的区间,b,c同,排序时,一律a在下,b在中,c在上~~

则初始区间信息:

       +--- 1
       |
   Pc  |
       |
       +--- 2/3
       |
   Pb  |
       |
       +--- 1/3
       |
   Pa  |
       |
       +--- 0


让我们来分析上面的accb字符串~~~

第一个字符是a,此时我们开始关注a的区间 0--1/3
由于a的出现,原来相等的概率发生了变化,此时Na=2,Nb=1,Nc=1,此时概率变为pa=2/4,pb=1/4,pc=1/4
我们对原来a的区间按照新概率进行重新划分


       +--- 1/3
       |
   Pc  |
       |
       +--- 1/4       (1/4)*(1/3-0)+1/6
       |
   Pb  |
       |
       +--- 1/6       (2/4)*(1/3-0)+0
       |
   Pa  |
       |
       +--- 0

 
第二个字符是c,此时我们开始关注c的区间 1/4--1/3
由于c的出现,原来的概率发生了变化,此时Na=2,Nb=1,Nc=2,此时概率变为pa=2/5,pb=1/5,pc=2/5
我们对原来c的区间按照新概率进行重新划分


       +--- 1/3
       |
   Pc  |
       |
       +--- 3/10       (1/5)*(1/3-1/4)+17/60
       |
   Pb  |
       |
       +--- 17/60       (2/5)*(1/3-1/4)+1/4
       |
   Pa  |
       |
       +--- 1/4

第三个字符是c,此时我们开始关注c的区间 3/10--1/3
由于c的出现,原来的概率发生了变化,此时Na=2,Nb=1,Nc=3,此时概率变为pa=2/6,pb=1/6,pc=3/6
我们对原来c的区间按照新概率进行重新划分

       +--- 1/3
       |
   Pc  |
       |
       +--- 19/60       (1/6)*(1/3-3/10)+14/45
       |
   Pb  |
       |
       +--- 14/45       (2/6)*(1/3-3/10)+3/10
       |
   Pa  |
       |
       +--- 3/10

最后一个是b,因为是最后一个字符,所以不再划分,此字符串最终区间即是b所在区间 14/45--19/60

程序要求,编写完整的main函数,以命令行的形式接收字符串,如程序被编译为442.exe,则442.exe accb,程序在标准控制台输出 14/45 19/60,中间留一空格~~~

字符串会精心构造,分母或分子都不会超过(unsigned long long)的表示范围~~

测试环境为gcc3.4.2
截止时间:下个星期一(10月16日)中午12点

有任何问题,请发帖讨论,或直接通过论坛发短消息给我~~

祝大家好运~~

回复列表 (共9个回复)

沙发

测试

板凳

#include <iostream>
#include <cstdlib>
using namespace std;

__int64 gcd (__int64 a, __int64 b)
{
    if (a < 0 || b < 0)
        return 0;
    else if(a == b)
        return a;
    else
    {
        for( ; a!=0 && b!=0; (a=a%b) && (b=b%a))
            ;
        return a | b;
    }
}

__int64 lcm(__int64 a, __int64 b)
{
    return a*b/gcd(a, b);
}
void FenshuAdd(__int64 a, __int64 b,__int64 c, __int64 d,__int64 &e, __int64 &f)
{
    f = lcm(b,d);
    e = a*(f/b) + c*(f/d);
    __int64 ntemp = gcd(e,f);
    if (ntemp > 1)
    {
        f = f/ntemp;
        e = e/ntemp;
    }
}
void FenshuDec(__int64 a, __int64 b,__int64 c, __int64 d,__int64 &e, __int64 &f)
{
    f = lcm(b,d);
    e = a*(f/b) - c*(f/d);
    __int64 ntemp = gcd(e,f);
    if (ntemp > 1)
    {
        f = f/ntemp;
        e = e/ntemp;
    }
}
int main()
{
    __int64 Boundry[8] = {0,1,1,3,2,3,1,1};
    int Amount[3] = {1,2,3};
    char DataIn[30];
    cout << "请输入由a,b,c小写字母组成的字符串:" << endl;//a == 97
    cin >> DataIn;
    for (int i = 0; i < strlen(DataIn); i++)
    {
        int NowV = (int)(DataIn[i]) - 97;
        for (int j = NowV; j < 3; j++)
        {
            Amount[j]++;
        }
        Boundry[0] = Boundry[NowV*2];
        Boundry[1] = Boundry[NowV*2 + 1];
        Boundry[6] = Boundry[NowV*2 + 2];
        Boundry[7] = Boundry[NowV*2 + 3];
        if (strlen(DataIn)-1 == i)
        {
            char   ch[30];   
            _i64toa(Boundry[0],ch,10);
            cout << ch <<"/";
            _i64toa(Boundry[1],ch,10);
            cout << ch <<" ";
            _i64toa(Boundry[6],ch,10);
            cout << ch <<"/";
            _i64toa(Boundry[7],ch,10);
            cout << ch <<endl;
            system("pause");
            return 0;
        }
        __int64 a = 0;
        __int64 b = 0;
        FenshuDec(Boundry[6],Boundry[7],Boundry[0],Boundry[1],a,b);
        FenshuAdd(Boundry[0],Boundry[1],a*Amount[0],b*Amount[2],Boundry[2],Boundry[3]);
        FenshuAdd(Boundry[0],Boundry[1],a*Amount[1],b*Amount[2],Boundry[4],Boundry[5]);
    }
    system("pause");
    return 0;
}


3 楼

在vs2003内编译测试通过


#include "stdafx.h"
/*
*定义一个分数类以及相应的操作
*并转换为真分数
*/
class REAL {
    unsigned long up;
    unsigned long down;
    public:
    REAL(unsigned long _up=0, unsigned long _down=1){
    unsigned long CommFac=GCD(_up,_down);
    up=_up/CommFac;
    down=_down/CommFac;
    }
    private:
    unsigned long GCD(unsigned long x,unsigned long y){
        unsigned long temp,r;
        if(x==0) return 1;
        if(x<y) {temp=y;y=x;x=temp;}        
        for(r=x%y;r;r=x%y) 
        { 
            x=y;y=r; 
        } 
        return y;
    }
    unsigned long GCM(unsigned long x,unsigned long y){
        return x*y/GCD(x,y);
        }
    public:
    REAL operator =(const REAL& r){
        this->up=r.up;
        this->down=r.down;
        return *this;
        }
    REAL operator -(const REAL& m){
        REAL res((this->up)*(m.down)-(m.up)*(this->down),(this->down)*(m.down));
        return res;
        }
    REAL operator +(const REAL& m){
        REAL res((this->up)*(m.down)+(m.up)*(this->down),(this->down)*(m.down));
        return res;
        }
    REAL operator*(const REAL& m){
        REAL res((this->up)*(m.up),(this->down)*(m.down));
        return res;
        }
    void ShowIt(){
        printf("<%ld/%ld> ",up,down);
        }
};

/*       Segment 类定义一个段
*        |----------|------|------|
*    start         p1     p2     end
*/
class Segment{

    REAL start;
    REAL p1;
    REAL p2;
    REAL end;
public:
    Segment():start(0,1),p1(1,3),p2(2,3),end(1,1){}
    encode(unsigned long a,unsigned long b,unsigned long c,char ch){
        switch(ch){
            case 'a':end=p1;break;
            case 'b':start=p1;end=p2;break;
            case 'c':start=p2;break;
            }
        REAL prop_a(a,a+b+c);/*计算比例*/
        REAL prop_b(b,a+b+c);
        /*调整点*/
        p1=start+(end-start)*prop_a;
        p2=p1+(end-start)*prop_b;
        }
    void printSeg(char cha){
        switch(cha){
            case 'a':start.ShowIt();p1.ShowIt();break;
            case 'b':p1.ShowIt();p2.ShowIt();break;
            case 'c':p2.ShowIt();end.ShowIt();break;
            default:printf("Invalid character\n");
            }
        }
    void printAll( ){
        start.ShowIt();p1.ShowIt();p2.ShowIt();end.ShowIt();printf("\n");
        }
        
};



int _tmain(int argc, _TCHAR* argv[])
{
    if (argc<2){
        printf("no input code\n");
        return 0;
        }
    char * ch=argv[1];
    Segment s;
    unsigned int N[3]={1,1,1};
    while(*ch){
        if(*(ch+1)=='\0') //如果是最后一个字母,输出编码
            {
            s.printSeg( *ch);
            break;
            }
        if((*ch=='a' )||(*ch=='b')||(*ch=='c')){
            N[*ch-'a']++;
            s.encode(N[0], N[1], N[2],*ch);
            //s.printAll();
            ch++;
            }
        else {
            printf("Invalid character\n");
            return 0;
        }
    }
    return 0;
}

4 楼

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void reduce(unsigned long *a,unsigned long *b)
{
    unsigned long i=*a,j=*b,temp;

    while(i!=0){
        temp=j%i;
        j=i;
        i=temp;
    }
    *a=*a/j;
    *b=*b/j;
}
int main(int argc,char *argv[])
{
    int i=0,l,na=1,nb=1,nc=1;
    unsigned long ma=0,mb=1,mc=2,md=3,ms,me,temp1;
    unsigned long ea=3,eb=3,ec=3,ed=3,es,ee,temp2;
    char *sPar;

    sPar=(char*)malloc(sizeof(char)*20);
    strcpy(sPar,argv[1]);
    l=strlen(sPar);

    while(i<=l-1){
        switch(*sPar){
        case 'a':
            ms=ma;me=mb;
            es=ea;ee=eb;
            na++;
            break;
        case 'b':
            ms=mb;me=mc;
            es=eb;ee=ec;
            nb++;
            break;
        case 'c':
            ms=mc;me=md;
            es=ec;ee=ed;
            nc++;
            break;
        default:
            printf("input error.return\n");
            return -1;
        }
        if(i==l-1) break;

        ma=ms;ea=es;

        temp1=na*(me*es-ms*ee);
        temp2=(na+nb+nc)*ee*es;
        reduce(&temp1,&temp2);
        mb=temp1*ea+temp2*ma;
        eb=temp2*ea;
        reduce(&mb,&eb);

        temp1=nb*(me*es-ms*ee);
        temp2=(na+nb+nc)*ee*es;
        reduce(&temp1,&temp2);
        mc=temp1*eb+temp2*mb;
        ec=temp2*eb;
        reduce(&mc,&ec);

        md=me;ed=ee;
        reduce(&md,&ed);
        sPar++;
        i++;
    }
    printf("%d/%d %d/%d\n",ms,es,me,ee);
    system("PAUSE");
    return 0;
}

5 楼

我是用vc6.0写的,由于vc6.0不支持unsigned long long ,程序中就只用了unsigned long,麻烦用gcc编译的时候帮我该一下,我没有用过gcc,还有如果有与vc不兼容的地方也帮我改下,谢谢了。

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;

unsigned long f(unsigned long x,unsigned long y)
{
    unsigned long k;
    k=(x>y?x:y);
    for(unsigned long i=k;i<x*y;i++)
    {
        if(i%x==0&&i%y==0)
            return i;
    }
    return x*y;
}

void f2(unsigned long &up,unsigned long &down)
{
    for(unsigned long i=up;i>1;i--)
        if(up%i==0&&down%i==0)
        {
            up=up/i;
            down=down/i;
        }
}

int main()
{
    string s;
    cout<<"输入字符串s:\n";
    cin>>s;
    unsigned long i,t,aup,adown,bup,bdown,cup,cdown,dup,ddown;
    long na,nb,nc,n;
    na=nb=nc=1;
    dup=0;
    aup=1;
    bup=2;
    cup=3;
    adown=bdown=cdown=ddown=3;
    for(i=0;i<s.length()-1;i++)
    {
        if(s[i]=='a')
        {
            na++;
            n=na+nb+nc;
            cup=aup;
            cdown=adown;
            t=f(cdown,ddown);
            adown=n*t;
            aup=na*(t/cdown*cup-t/ddown*dup)+dup*n;
            bdown=f((n*t),adown);
            bup=(bdown/(n*t))*(t/cdown*cup-t/ddown*dup)*nb+bdown/adown*aup;
        }
        else if(s[i]=='b')
        {
            nb++;
            n=na+nb+nc;
            cup=bup;
            cdown=bdown;
            dup=aup;
            ddown=adown;
            t=f(cdown,ddown);
            adown=n*t;
            aup=na*(t/cdown*cup-t/ddown*dup)+dup*n;
            bdown=f((n*t),adown);
            bup=(bdown/(n*t))*(t/cdown*cup-t/ddown*dup)*nb+bdown/adown*aup;
        }
        else if(s[i]=='c')
        {
            nc++;
            n=na+nb+nc;
            dup=bup;
            ddown=bdown;
            t=f(cdown,ddown);
            adown=n*t;
            aup=na*(t/cdown*cup-t/ddown*dup)+dup*n;
            bdown=f((n*t),adown);
            bup=(bdown/(n*t))*(t/cdown*cup-t/ddown*dup)*nb+bdown/adown*aup;
        }
        else 
        {
            cerr<<"error!\n";
            exit(0);
        }
    }
    if(s[i]=='a')
    {
        f2(dup,ddown);
        f2(aup,adown);
        if(dup==0)
            cout<<dup<<"  ";
        else
            cout<<dup<<"/"<<ddown<<"  ";
        cout<<aup<<"/"<<adown<<endl;
    }
    else if(s[i]=='b')
    {
        f2(aup,adown);
        f2(bup,bdown);
        cout<<aup<<"/"<<adown<<"  ";
        cout<<bup<<"/"<<bdown<<endl;
    }
    else if(s[i]=='c')
    {
        f2(bup,bdown);
        f2(cup,cdown);
        cout<<bup<<"/"<<bdown<<"  ";
        if(cdown==1)
          cout<<cup<<endl;
        else
          cout<<cup<<"/"<<cdown<<endl;

    }
    else 
    {
        cerr<<"error!\n";
        exit(0);
    }
    return 0;
}

6 楼


  我的编译环境是VC6.0,楼主的unsigned long long 真要了我的命,楼主难道是推行64位机的宣传者??????[em14][em18]

#include "stdio.h"
#include "windows.h"
typedef unsigned __int64 u64;

//ab最大公约数×ab最小公倍数=a×b
u64 gy(u64 x,u64 y)   
{   
    u64 z;
    while(y>0)
    {
        z = x % y;
        x =y;
        y = z;
    }
    return x;
}

void add(u64 &p1,u64 &p2,u64 &p3,u64 &p4,u64 &p5,u64 &p6)
{
    u64 temp = p2*p4/gy(p2,p4);
    p5 = p1*temp/p2 + p3*temp/p4;
    p6 = temp;
    temp = gy(p5,p6);
    if(temp==1)
        return;
    p5 /= temp;
    p6 /= temp;
}

void sub(u64 &p1,u64 &p2,u64 &p3,u64 &p4,u64 &p5,u64 &p6)
{
    u64 temp = p2*p4/gy(p2,p4);
    p5 = p1*temp/p2 - p3*temp/p4;
    p6 = temp;
    temp = gy(p5,p6);
    if(temp==1)
        return;
    p5 /= temp;
    p6 /= temp;
}

void mul(u64 &p1,u64 &p2,u64 &p3,u64 &p4,u64 &p5,u64 &p6)
{
    u64 temp;
    p5 = p1 * p3;
    p6 = p2 * p4;
    temp = gy(p5,p6);
    if(temp==1)
        return;
    p5 /= temp;
    p6 /= temp;
}

void printu64(u64 p1,u64 p2,u64 p3,u64 p4)
{
    int i,r;
    u64 s;
    char str[21];

    i=0;
    s = p1;
    while (s)
    {
        r = s%10;
        s = s/10;
        str[i++] = r+'0';
    }
    str[i] = 0;
    strrev(str);
    printf("%s",str);
    if(p1==0)
        printf("0");

    printf("/");

    i=0;
    s = p2;
    while (s)
    {
        r = s%10;
        s = s/10;
        str[i++] = r+'0';
    }
    str[i] = 0;
    strrev(str);
    printf("%s",str);
    if(p2==0)
        printf("0");

    printf(" ");

    i=0;
    s = p3;
    while (s)
    {
        r = s%10;
        s = s/10;
        str[i++] = r+'0';
    }
    str[i] = 0;
    strrev(str);
    printf("%s",str);
    if(p3==0)
        printf("0");
    
    printf("/");
    
    i=0;
    s = p4;
    while (s)
    {
        r = s%10;
        s = s/10;
        str[i++] = r+'0';
    }
    str[i] = 0;
    strrev(str);
    printf("%s",str);
    if(p4==0)
        printf("0");
    
    printf("\n");
}


main(int argc,char **argv)
{
    if(argc!=2)
        return;
    int i,len;
    u64 Nabc[3] = {1,1,1};
    u64 n0,n1,n2,nt,m0,m1,m2,mt,temp,Ntotal = 4;

    len = strlen(argv[1]);
    char str[50];
    strcpy(str,argv[1]);
    

    n1 = str[0]-'a';
    n2 = n1 + 1;
    m1 = m2 = 3;

    for(i=0;i<len-1;i++,Ntotal++)
    {
        Nabc[str[i]-'a']++;
        sub(n2,m2,n1,m1,n0,m0);
        
        if(str[i+1]=='a')
        {
            mul(n0,m0,Nabc[0],Ntotal,n0,m0);
            add(n0,m0,n1,m1,n2,m2);
        }
        else if(str[i+1]=='b')
        {
            nt = n0;
            mt = m0;

            mul(n0,m0,Nabc[0],Ntotal,n0,m0);
            add(n0,m0,n1,m1,n1,m1);

            ////////////////////

            n0 = nt;
            m0 = mt;
            
            mul(n0,m0,Nabc[1],Ntotal,n0,m0);
            add(n0,m0,n1,m1,n2,m2);
            
        }
        else if(str[i+1]=='c')
        {
            temp = Nabc[0]+Nabc[1];
            mul(n0,m0,temp,Ntotal,n0,m0);
            add(n0,m0,n1,m1,n1,m1);
        }
    }
    printu64(n1,m1,n2,m2);    
}

7 楼

没有时间了,有一些地方没有优化,但是不知道能不能满足要求,
#include<iostream.h>

struct Fensu
{
    unsigned long int fenzi;
    unsigned long int fenmu;
};
    
    class Suanshu
    {
        Fensu a[4];
        int n_a,n_b,n_c;
        int num;
    public:
        Suanshu()
        {
            n_a=n_b=n_c=1;
            num=3;
            for(int i=0;i<4;i++)
            {
                a[i].fenzi=i;
                a[i].fenmu=3;
            }
        }
        ~Suanshu(){};
        
        void bianma(Fensu& begin,Fensu& end);
        void output(char& p);
        void input(char& p)
        {
            switch(p)
            {
            case'a':n_a++;num++;bianma(a[0],a[1]);break;
            case'b': n_b++;num++;bianma(a[1],a[2]);break;
            case'c': n_c++;num++;bianma(a[2],a[3]);break;
            default:cout<<"Input character is error!"<<endl;break;
            }
        }
    };

    void Suanshu::bianma(Fensu &begin,Fensu &end)
    {
        int zi,mu;
        if(end.fenzi-begin.fenzi==0)
            zi=end.fenzi;
        else
            zi=end.fenzi-begin.fenzi;
        mu=end.fenmu;
        a[0].fenzi=begin.fenzi*zi;
        a[1].fenzi=a[0].fenzi+n_a*zi;
        a[2].fenzi=a[1].fenzi+n_b*zi;
        a[3].fenzi=a[2].fenzi+n_c*zi;
        for(int i=0;i<4;i++)
            a[i].fenmu=mu*num;
    }
    void Suanshu::output(char &p)
    {
        switch(p)
        {
        case'a':cout<<a[0].fenzi<<"/"<<a[0].fenmu<<"and"<<a[1].fenzi<<'/'<<a[1].fenmu<<endl;break;

        case'b':cout<<a[0].fenzi<<"/"<<a[0].fenmu<<"and"<<a[1].fenzi<<'/'<<a[1].fenmu<<endl;break;
        case'c':cout<<a[0].fenzi<<"/"<<a[0].fenmu<<"and"<<a[1].fenzi<<'/'<<a[1].fenmu<<endl;break;
        default:break;
        }
    }

    int main(void)
    {
        Suanshu kaka;
        char a[20];
        char *p;
        cin>>a;
        p=a;
        while(*p!='\0')
        {
            kaka.input(*p);
            p++;
        }
        p--;
        kaka.output(*p);
        return 0;
    }

8 楼

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX 50

unsigned long ma=0,mb=1,mc=2,md=3,ms=0,me=3;
unsigned long ea=3,eb=3,ec=3,ed=3,es=0,ee=3;

unsigned long HCF(unsigned long a,unsigned long b)
{
    unsigned long temp;

    if(a>b){
        temp=a;
        a=b;
        b=temp;
    }
    while(a!=0){
        temp=b%a;
        b=a;
        a=temp;
    }
    return b;
}
void reduce(unsigned long *a,unsigned long *b)
{
    unsigned long temp;

    temp=HCF(*a,*b);
    *a=*a/temp;
    *b=*b/temp;
}
void change(unsigned long a,unsigned long b,unsigned long c,unsigned long d1,
        unsigned long d2,unsigned long e1,unsigned long e2,unsigned long f1,
        unsigned long f2,unsigned long *m1,unsigned long *m2)
{
    unsigned long temp,temp1,temp2,c1,c2;
    c1=a;
    c2=a+b+c;
    reduce(&c1,&c2);
    reduce(&d1,&d2);
    reduce(&e1,&e2);
    reduce(&f1,&f2);
    temp=HCF(d2,e2);
    temp1=e2/temp*d1-d2/temp*e1;
    temp2=e2/temp*d2;
    reduce(&temp1,&temp2);
    reduce(&c1,&temp2);
    reduce(&c2,&temp1);
    temp1=c1*temp1;
    temp2=c2*temp2;
    temp=HCF(temp2,f2);
    *m1=f2/temp*temp1+temp2/temp*f1;
    *m2=f2/temp*temp2;
    reduce(m1,m2);
}
int main(int argc,char *argv[])
{
    int i=0,l,na=1,nb=1,nc=1;
    char *sPar;

    sPar=(char*)malloc(sizeof(char)*MAX);
    strcpy(sPar,argv[1]);
    l=strlen(sPar);
    while(i<=l-1){

        switch(*sPar){
        case 'a':
            ms=ma;me=mb;
            es=ea;ee=eb;
            na++;
            break;
        case 'b':
            ms=mb;me=mc;
            es=eb;ee=ec;
            nb++;
            break;
        case 'c':
            ms=mc;me=md;
            es=ec;ee=ed;
            nc++;
            break;
        default:
            printf("input error.return\n");
            return -1;
        }
        if(i==l-1) break;

        ma=ms;ea=es;
        change(na,nb,nc,me,ee,ms,es,ma,ea,&mb,&eb);
        change(nb,na,nc,me,ee,ms,es,mb,eb,&mc,&ec);
        md=me;ed=ee;
        sPar++;
        i++;
    }
    printf("%d/%d %d/%d\n",ms,es,me,ee);
    system("PAUSE");
    return 0;
}

9 楼

比赛时间到~~~

我来回复

您尚未登录,请登录后再回复。点此登录或注册