主题:第44次编程比赛第二题~~
孤独的猫 [专家分:3370] 发布于 2006-10-15 23:29:00
算术编码是已知的最接近理论极限的压缩算法~~
下面这题就是仿照其出的~~
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个回复)
沙发
孤独的猫 [专家分:3370] 发布于 2006-10-12 21:26:00
测试
板凳
hotzenplotz [专家分:40] 发布于 2006-10-13 15:01:00
#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 楼
gz80 [专家分:0] 发布于 2006-10-13 20:02:00
在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 楼
tenm [专家分:330] 发布于 2006-10-13 20:52:00
#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 楼
flypampas [专家分:30] 发布于 2006-10-14 16:05:00
我是用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 楼
scanf [专家分:380] 发布于 2006-10-14 16:48:00
我的编译环境是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 楼
xylgg [专家分:800] 发布于 2006-10-16 11:22:00
没有时间了,有一些地方没有优化,但是不知道能不能满足要求,
#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 楼
tenm [专家分:330] 发布于 2006-10-16 11:50:00
#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 楼
孤独的猫 [专家分:3370] 发布于 2006-10-16 12:35:00
比赛时间到~~~
我来回复