求助,德国大学的算法作业!

bjtoto 2002-05-17 09:10:23
这里是德国一大学本科计算机算法的一道上机题,要求使用循环密码加密文件,主要思路是:利用非线性公式:X(n+1)=a*X(n)-a*X(n)*X(n)对所读取的文件的每一个字符进行加密,其中,a是常数,X(0)的值给定。也就是说,对应的每个文件字符(二进制),通过计算X(n)的值,再与之相加,则得到相应被加密的字符,最后再输出到文件。

问题是:对于非线性公式,X(n+1)=a*X(n)-a*X(n)*X(n),当n很大的时候(n>10000)(n其实是文件的大小),计算量则会很大,现在要求优化算法以减少程序执行时间。

我写出了自己的求X(n)的函数,但不知道如何优化,请求各位高手帮助,代码如下:

#include <stdio.h>
#include <time.h>
#include <iostream.h>
#include <math.h>

#define origXn 0.1234
#define a 4

class cal
{
public:
double Xn(int n);
void MainCal(int n);

private:
int *inp;
int *shift;
int *out;
double *Xn_array;
};

double cal::Xn(int n)
{
int i;

Xn_array[0] = origXn;

for(i=1;i<=n;i++)
{
Xn_array[i] = a*Xn_array[i-1] - a*Xn_array[i-1]*Xn_array[i-1];
}
return Xn_array[n];
}

void cal::MainCal(int n)
{
int i;
inp = new int[n];
shift = new int[n];
out = new int[n];
Xn_array = new double[n];


for(i=0;i<n;i++)
{
shift[i] = (int)(Xn(i)*1000);
}
}

void main(void)
{
int num;
cal pro;
num = 40000; // this value is related with the length of file

clock_t startClock = clock();

cout<<"Please wait....."<<endl;

pro.MainCal(num);

cout<<"The program has run : "<<clock()-startClock<<" seconds"<<endl;

}
...全文
82 38 打赏 收藏 转发到动态 举报
写回复
用AI写文章
38 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhiyong82 2002-05-27
  • 打赏
  • 举报
回复
我觉得这个问题不能从数学式上去优化算法,因为对于我们来说,一个算法的优劣是由它的时间度和空间度来决定,所以我觉得这个问题应该从减少变量来优化算法,而计算等用一两个循环来。这是我的个人意见,答案正不正确还是个未知!
kzzk 2002-05-27
  • 打赏
  • 举报
回复
不明白 式子要表達的意思

到底 x(0) ;x(1) ;x(n) 都是一個定值

只要知道n就行 是不是?
BabyBlue_Wang 2002-05-25
  • 打赏
  • 举报
回复
直接改成这样不行吗?
double cal::Xn(int n)
{
Xn_array[n] = a*Xn_array[n-1]*( 1-Xn_array[n-1]);
return Xn_array[n];
}

bjyjy 2002-05-23
  • 打赏
  • 举报
回复
X(n+1)=a*x(n)-a*x(n)*x(n)
=a*x(n)[1-x(n)]

或者:
x(0)=给定值;
t=x(0);
for (i=1; i<n; i++)
{
x(i)=a*t*(1-t);
t=x(i);
} ;
有那么复杂吗,搞不懂
sinock 2002-05-23
  • 打赏
  • 举报
回复
非常赞成youngren(芝麻程序) 的说法
cnwolfs 2002-05-22
  • 打赏
  • 举报
回复
这么简单的题目怎么这么复杂了,真是“(你不说我倒还明白,你越说我越糊涂) ”,还以为有什么大不了的
取出文件,从1开始,按顺序用一个算一个,保存上一个数字即可,不用算法解决,只要使用程序解决就可以了
seamanhailing 2002-05-21
  • 打赏
  • 举报
回复
不用使用数组,只要有Xn和X(n+1)就行了。Xn在使用完以后就被替换掉了。
seamanhailing 2002-05-21
  • 打赏
  • 举报
回复
不要用递归,用循环更好因为每一个Xn都有用,递归消耗系统资源比较大。
szbobby 2002-05-20
  • 打赏
  • 举报
回复
笨蛋,X(n+1)=a*X(n)-a*X(n)*X(n),若改做X(n+1)=a*X(n)*(1-X(n))岂不至少提高25%?
airlulu 2002-05-20
  • 打赏
  • 举报
回复
不要提递归了,肯定溢出的~
老南 2002-05-20
  • 打赏
  • 举报
回复
不理解。什么是key? a?X(0)?我怀疑。
Li_Dinosaur 2002-05-19
  • 打赏
  • 举报
回复
UP
knl 2002-05-18
  • 打赏
  • 举报
回复
真是既然能加密问什么不会解密!!!
纯粹想省懒法!!!!去去去!!!!想玩计算机就不要偷懒!!!!
想编程就更不要偷懒!!!!!!
sblh 2002-05-18
  • 打赏
  • 举报
回复
先解出来再出X(N)的值
gofire 2002-05-17
  • 打赏
  • 举报
回复
同意tlfly(一意孤行)和zxl19790710(雪龙)的建议,你重复计算了。
pplover 2002-05-17
  • 打赏
  • 举报
回复
德国大学怎么这么弱啊?
配方学过没有?
X(n+1)=a*X(n)-a*X(n)*X(n)
不就是
X(n+1)=a(1/2-X(n))的平方减a/4
这不就简化了算法吗?
zxl19790710 2002-05-17
  • 打赏
  • 举报
回复
void cal::MainCal(int n)
{
int i;
inp = new int[n];
shift = new int[n];
out = new int[n];
Xn_array = new double[n];
Xn(n);

for(i=0;i<n;i++)
{
shift[i] = (int)(Xn_array[i]*1000);
}
}
这样就避免了重复计算
bjtoto 2002-05-17
  • 打赏
  • 举报
回复
加密解密的主要函数如下:

/* Here is the main equation of algorithms: out[n] = inp[n] + shift[n]. out[n] is the decrped code, inp[n] is the original file code(ASCII code) and shift[n] is the discrete value depending on X(n).*/

// ----- EncrypFile() -----------------------------------------------
int map::EncrypFile(char *orig_name,char *des_name)
{
FILE *fp1,*fp2;
int ch,i;
int MAX;
int *p;

fp1 = fopen(orig_name,"rb");
if(fp1==NULL)
{
cout<<"Can not open file!"<<endl;
exit(1);
}

ini(orig_name);
MAX = this->Flen;
cout<<MAX<<endl;
exit(1);
shiftFunc(MAX);

for(i=0;i<MAX;i++)
{
ch = fgetc(fp1);
inp[i] = (char)ch;
}

for(i=0;i<MAX;i++)
{
int temp=0;
out[i] = inp[i] + shift[i];
while(out[i]>126)
{
temp = (int)fmod(shift[i],126);
out[i] = inp[i] + temp;
if(out[i]>126)
out[i] = (int)fmod(out[i],126);
}

}

if((fp2 = fopen(des_name,"wb+")) == NULL)
{
cout<<"Output file fail!"<<endl;
exit(1);
}

p = out;
for(i=0;i<MAX;i++) fputc( (char)(*(p++)), fp2 );

fclose(fp1);
fclose(fp2);
free(inp);
free(shift);
free(out);
free(Xn_array);

return 0;
}



// ----- DecrypFile() -----------------------------------------------
int map::DecrypFile(char *orig_name,char *des_name)
{

FILE *fp3,*fp4;
int MAX;
int ch,i;
int *p;

fp3 = fopen(orig_name,"rb");
if(fp3==NULL)
{
cout<<"Can not open file!"<<endl;
exit(1);
}

ini(orig_name);
MAX = this->Flen;
shiftFunc(MAX);

for(i=0;i<MAX;i++)
{
ch = fgetc(fp3);
out[i] = (char)ch;
}

for(i=0;i<MAX;i++)
{
int temp=0;

if(out[i]>shift[i])
inp[i] = out[i] - shift[i];
else
if(out[i]>fmod(shift[i],126))
{
inp[i] = out[i] - (int)fmod(shift[i],126);
}
else
inp[i] = out[i] + 126 - (int)fmod(shift[i],126);
}

if((fp4 = fopen(des_name,"wb+")) == NULL)
{
cout<<"Output file fail!"<<endl;
exit(1);
}

p = inp;
for(i=0;i<MAX;i++) fputc( (char)(*(p++)), fp4 );

fclose(fp3);
fclose(fp4);
free(inp);
free(shift);
free(out);
free(Xn_array);

return 0;
}
bjtoto 2002-05-17
  • 打赏
  • 举报
回复
有几点我想补充:
1.用递归方法我曾经试过,但n的值稍微一大就会堆栈溢出,所以我认为可能用递归方法不妥。

2.shift[i] = (int)(Xn(i)*1000);是老师规定的格式,为的是得到0到1000之间的整数。

3.可以这样说,每个X(n+1)的值,都取决于它的前一个值。这种形式其实最后用递归做,我是我试过,n一旦变大,则不行。

4.用我的这种方法,不会产生递归溢出问题,但效率很低。

谢谢tlfly(一意孤行)同志提出的,在使用new以后用delete释放空间的建议。
bjtoto 2002-05-17
  • 打赏
  • 举报
回复
特别感谢 attainment(取) 朋友所提供的改正方法,程序执行速度的确有了本质的提高,看样子我必须得考虑程序的结构问题。谢谢。
加载更多回复(18)

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧