当前位置: 首页 > news >正文

最大乘积——高精度乘法

乘积最大

Description

问题描述:
今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样
一道题目:


设有一个长度N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。
同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:有一个数字串: 312,当N=3,K=1时会有以下两种分法:
1)3*12=36
2)31*2=62
这时,符合题目要求的结果是: 31*2=62
现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。

Input

程序的输入共有两行:
第一行共有2个自然数N,K (6<=N<=40,1<=K<=6)
第二行是一个K度为N的数字串。

Output

结果显示在屏幕上,相对于输入,应输出所求得的最大乘积(一个自然数)。

Sample Input

4 2
1231

Sample Output

62
状态转移方程:

f[i][j]=max{f[i-1][m]*a[m..j]} i<=m<=j

f[i][j]代表前j个数用i个乘号连接得到的最大值,a[m..j]代表从a[]的第m个到第j个数字组成的数。转移方程不算难,但此题要用

高精度乘法。乘法有两种写法:一种是完全模拟乘法竖式的演算过程,另一种是通过总结规律得到的算法。下面列出两种程序的写法。

法一:

 

ContractedBlock.gif ExpandedBlockStart.gif 代码

   
1 #include < stdio.h >
2 #include < stdlib.h >
3 #include < string .h >
4 char f[ 7 ][ 41 ][ 2010 ],a[ 40 ],b[ 2000 ];
5 int n,k,length[ 7 ][ 41 ];
6 /*length[][]记录高精度数的长度*/
7 int plus( char * p, int l1, char * q, int l2, int le)
8 {
9 int c,s = 0 ,l;
10 int i;
11 for (i = l1 - 1 ;i >= 0 ;i -- )p[i + le] = p[i];
12 for (i = 0 ;i < le;i ++ )//对错位的处理:后移与前几位补0,因为数值是倒存的
13 {
14 p[i] = ' 0 ' ;
15 l1 ++ ;
16 }
17 if (l1 > l2)l = l1;
18 else l = l2;
19
20 for (i = 0 ;i < l;i ++ )
21 {
22 s += p[i] + q[i] - 2 * ' 0 ' ;
23 c = s % 10 ;
24 s /= 10 ;
25 q[i] = c + ' 0 ' ;
26 }
27 while (s != 0 )
28 {
29 c = s % 10 ;
30 s /= 10 ;
31 q[i ++ ] = c + ' 0 ' ;
32 }
33
34 return i;
35 }
36
37 int mul( char * p, int l1, int fr, int l2, char * q, int l3)
38 {
39 int c,s = 0 ;
40 int i,j;
41 char s1[ 40 ],s2[ 2000 ];//s1[]记录a[]中从fr开始,长度为l2的数
42 for(i=0;i<l2;i++ )
43 s1[i]=a[l2+fr-i-1 ];
44 for (i = 0 ;i < l1;i ++ )//用s1[]的每一位乘以p[]的每一位,注意错位的
45 if (p[i] != ' 0 ' )//是0就不必乘了
46 {
47 memset(s2, 48 , sizeof (s2));
48 for (j = 0 ;j < l2;j ++ )
49 {
50 s += (p[i] - ' 0 ' ) * (s1[j] - ' 0 ' );
51 c = s % 10 ;
52 s = s / 10 ;
53 s2[j] = c + ' 0 ' ;
54 }
55 while (s != 0 )
56 {
57 c = s % 10 ;
58 s /= 10 ;
59 s2[j ++ ] = c + ' 0 ' ;
60 }
61 l3 = plus(s2,j,q,l3,i);//q[]中存每一位乘过后的值
62 }
63 return l3;
64 }
65
66
67 int max( char * p, char * q, int l1, int l2)
68 {
69 if (l1 > l2) return 1 ;
70 else if (l2 > l1) return 0 ;
71 else
72 {
73 int i;
74 for (i = l1 - 1 ;i >= 0 ;i -- )
75 if (p[i] > q[i]) return 1 ;
76 else if (q[i] > p[i]) return 0 ;
77 return 0 ;
78 }
79 }
80
81 int main()
82 {
83 FILE * in , * out ;
84 in = fopen( " maxmu3.in " , " r " );
85 out = fopen( " maxmu.out " , " w " );
86 int i,j,k,m,l1,l2,i1;
87 fscanf( in , " %d %d " , & n, & k);
88 fscanf( in , " %s " ,a);
89
90 memset(f, 48 , sizeof (f));//不能初始化为0,因为f[][][]是字符型,字符型0的ASCII码是48
91 memset(length, 0 , sizeof (length));
92 for(i=1;i<=n;i++ )
93 {
94 for(j=0;j<i;j++ )
95 f[0][i][j]=a[i-j-1 ];
96 length[0][i]= i;
97 }
98
99 for (i = 1 ;i <= k;i ++ )
100 for (j = i + 1 ;j <= n;j ++ )
101 {
102 length[i][j] = mul(f[i - 1 ][i],length[i - 1 ][i],i,j - i,f[i][j],length[i][j]);
103 for (m = i + 1 ;m <= j;m ++ )
104 {
105 memset(b, 48 , sizeof (b));//每次都要初始化
106 l1 = mul(f[i - 1 ][m],length[i - 1 ][m],m,j - m,b, 0 );
107 if (max(b,f[i][j],l1,length[i][j]))
108 {
109 memset(f[i][j], 48 , sizeof (f[i][j]));//有必要先将f[i][j]清空
110 strcpy(f[i][j],b);
111 length[i][j] = l1;
112 }
113 }
114 }
115
116 for (i = length[k][n] - 1 ;i >= 0 ;i -- )
117 fprintf(out,"%c",f[k][n][i]);
118 fprintf(out,"\n");
119 fclose(in);
120 fclose(out);
121 return 0;
122 }

举例说明:123*456列为竖式计算是:

1 2 3

* 4 5 6

————————

 

7 3 8 ————由mul()函数计算可得

6 1 5

4 9 2

————————

5 6 0 8 8
最后将中间红色区的数加起来的工作就由plus()函数做了。注意plus()还要处理错位。
法二:

 
ContractedBlock.gif ExpandedBlockStart.gif 代码

   
1 int mul( int * p, int l1, int fr, int l2, int * q, int l3)
2 {
3 int i,j;
4 int c,s = 0 ;
5 int s1[ 40 ];
6
7 for (i = 0 ;i < l2;i ++ )
8 s1[i] = a[l2 + fr - i - 1 ];
9
10 for (i = 0 ;i < l1;i ++ )
11 for (j = 0 ;j < l2;j ++ )
12 q[i + j] = q[i + j] + p[i] * s1[j];
13
14 for (i = 0 ;i <= l1 + l2 - 2 ;i ++ )
15 {
16 c = (q[i] + s) % 10 ;
17 s = (q[i] + s) / 10 ;
18 q[i] = c;
19 }
20
21 while (s != 0 )
22 {
23 c = (q[i] + s) % 10 ;
24 s = (q[i] + s) / 10 ;
25 q[i ++ ] = c;
26 }
27 return i;
28 }

 

注意法二已将字符串转化为了int型,其他没变。该方法是这样相乘的:
q[i+j]=q[i+j]+s1[j]*p[i];
最后再处理进位,显然比法一要简单多。
当然还有不用高精度的方法,也列出来了。

 
ContractedBlock.gif ExpandedBlockStart.gif 代码

   
1 #include < stdio.h >
2 #include < stdlib.h >
3 #include < string .h >
4 long f[ 7 ][ 41 ];
5 char a[ 40 ];
6 int n,k;
7
8 int mul( int x, int f, int le)
9 {
10 int i,s = 0 ,m = 1 ;
11 for(i=le-1;i>=0;i-- )
12 { s +=(a[i+f]-'0')* m;
13 m*=10 ;
14 }
15 return s * x;
16
17 }
18 int main()
19 {
20 FILE * in , * out ;
21 in = fopen( " maxmu1.in " , " r " );
22 out = fopen( " maxmu.out " , " w " );
23 int i,j,k,m,sum;
24 long max;
25 char x;
26 fscanf( in , " %d %d " , & n, & k);
27 fscanf( in , " %s " ,a);
28
29 for(i=1;i<=n;i++ )
30 {
31 sum=0;m=1 ;
32 for(j=i-1;j>=0;j--)
33 {
34 sum+=(a[j]-'0')* m;
35 m*=10 ;
36 }
37 f[0][i]= sum;
38 }
39
40 for (i = 1 ;i <= k;i ++ )
41 for (j = i + 1 ;j <= n;j ++ )
42 {
43 f[i][j] = mul(f[i - 1 ][i],i,j - i);
44 for (m = i + 1 ;m <= j;m ++ )
45 {
46 max = mul(f[i - 1 ][m],m,j - m);
47 if (f[i][j] < max)
48 f[i][j] = max;
49 }
50 }
51
52 fprintf( out , " %ld " ,f[k][n]);
53 fclose( in );
54 fclose( out );
55 return 0 ;
56 }
57

 

状态转移还一样,只是这次可以直接乘,所以在数的存储处理上不必倒着存(上面两个完整程序中红色区域是对数的存储处理)。

转载于:https://www.cnblogs.com/aiyite826/archive/2010/08/05/1793245.html

相关文章:

  • ZT:判断链表是否有环以及环的入口点
  • mfs 测试实验--环境搭建
  • linux 入门学习
  • 报ERROR: Fast Data Access MMU Miss 错误解决思路
  • ASP.NET获取当前网址方法
  • 如果你已经20岁了,你真的输不起了,别再孩子了.....
  • SQL的语法和规则
  • 漫谈VoIP技术 H.323与SIP比较分析
  • FreeBSD 6.0架设管理与应用-第二章 安裝 FreeBSD
  • MyIsam 锁
  • Eqs--POJ 1840
  • gui2exe
  • NeHe OpenGL第三十九课:物理模拟
  • 珀耳帖效应
  • 主机与显示器不兼容故障分析排除
  • 【React系列】如何构建React应用程序
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • Apache Pulsar 2.1 重磅发布
  • CSS 专业技巧
  • CSS实用技巧
  • egg(89)--egg之redis的发布和订阅
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • linux安装openssl、swoole等扩展的具体步骤
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • tab.js分享及浏览器兼容性问题汇总
  • ucore操作系统实验笔记 - 重新理解中断
  • Unix命令
  • 阿里云Kubernetes容器服务上体验Knative
  • 不上全站https的网站你们就等着被恶心死吧
  • 初识 webpack
  • 记录:CentOS7.2配置LNMP环境记录
  • 简单数学运算程序(不定期更新)
  • 看域名解析域名安全对SEO的影响
  • 前端js -- this指向总结。
  • 微服务入门【系列视频课程】
  • 详解NodeJs流之一
  • 在weex里面使用chart图表
  • 进程与线程(三)——进程/线程间通信
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • ###C语言程序设计-----C语言学习(3)#
  • (八十八)VFL语言初步 - 实现布局
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (黑马C++)L06 重载与继承
  • (十六)Flask之蓝图
  • (转)shell调试方法
  • .NET Standard 的管理策略
  • .NET 常见的偏门问题
  • .net 设置默认首页
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .net经典笔试题
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [3D游戏开发实践] Cocos Cyberpunk 源码解读-高中低端机性能适配策略
  • [AutoSar]BSW_Memory_Stack_003 NVM与APP的显式和隐式同步