第 9 章 组合问题与大数运算 9.1 大数运算 在计算机中, 长整型变量的范围是 至 , 若用长整型变量做乘法运算, 乘积最多不能超过 10 位数 即便用双精度型 (double) 变量, 也仅能保证 16 位有效数字的精度 在某些需要更高精度的乘法运算

Similar documents
用 照 片 說 故 事 舊 區 有 舊 區 的 故 事, 它 沒 有 高 聳 入 雲 的 大 廈, 沒 有 縱 橫 交 錯 的 天 橋 沒 有 五 彩 繽 紛 的 商 場, 更 沒 有 林 林 總 總 的 名 牌, 有 的 只 是 差 點 被 人 遺 忘 的 東 西 又 一 城 時 代 廣 場 IF

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

二 招 生 类 别 及 人 数 音 乐 体 育 美 术 共 计 划 招 收 30 人 体 育 :7 人, 其 中 田 径 3 人 羽 毛 球 2 人 篮 球 2 人 ( 篮 球 只 招 男 生 ) 美 术 :15 人 音 乐 :8 人, 其 中 器 乐 3 人 声 乐 2 人 舞 蹈 3 人 三 报

Ps22Pdf


《拍案惊奇》(中)

求出所有的正整数 n 使得 20n + 2 能整除 2003n n 20n n n 20n n 求所有的正整数对 (x, y), 满足 x y = y x y (x, y) x y = y x y. (x, y) x y =

避孕篇

育儿知识100问(二)

% % % %!""# %!""#!""& (! ) & * % %!""#!""#!""& % % % % % % % % % %!%!) % % % % % %!,$!!!!!!! -.$!!! /-,$!!!!!!!! $!"

2010年中级 统计工作实务 试卷(A)

山东2014第四季新教材《会计基础》冲刺卷第二套

Microsoft Word - 第5-7章

幻灯片 1

chap07.key


校园之星

《晚年周恩来》目录


第一章三角函数 1.3 三角函数的诱导公式 A 组 ( ) 一 选择题 : 共 6 小题 1 ( 易诱导公式 ) 若 A B C 分别为 ABC 的内角, 则下列关系中正确的是 A. sin( A B) sin C C. tan( A B) tan C 2 ( 中诱导公式 ) ( ) B. cos(

新婚夫妇必读(二十二).doc

优合会计考点直击卷子之财经法规答案——第八套

. (A) (B) (C) A (D) (E). (A)(B)(C)(D)(E) A

Ps22Pdf

C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1

北京2014年会计从业资格考试《会计基础》备考机试卷一

2. 下 列 理 解 和 分 析, 不 符 合 原 文 意 思 的 一 项 是 ( ) A. 水 手 在 伦 敦 讲 东 印 度 群 岛 的 所 见 所 闻, 匠 人 在 火 炉 边 讲 自 己 的 人 生 经 历, 他 们 讲 的 故 事 各 有 特 点, 但 同 属 于 传 统 故 事 模 式

Ps22Pdf

数 学 高 分 的 展 望 一 管 理 类 联 考 分 析 第 一 篇 大 纲 解 析 篇 编 写 : 孙 华 明 1 综 合 能 力 考 试 时 间 :014 年 1 月 4 日 上 午 8:30~11:30 分 值 分 配 : 数 学 :75 分 逻 辑 :60 分 作 文 :65 分 ; 总

Microsoft PowerPoint - 01_Introduction.ppt

A.68 B.70 C.80 D.100 答 案 A 解 析 丁 产 品 的 可 变 现 净 值 =110-2=108( 万 元 ), 成 本 =100+40=140( 万 元 ), 可 变 现 净 值 低 于 成 本, 产 品 发 生 的 减 值, 所 以 丙 材 料 的 可 变 现 净 值 =1

< F20B4F2D3A1D7F7D2B5>

腊八粥的来历 南宋陆游诗云 今朝佛粥更相馈 反觉江村节 物新 说的就是腊八粥 可见 腊八节 吃 腊八 粥 的风俗 由来已久 每逢腊八这一天 不论是朝 廷 官府 寺院还是黎民百姓家都要做腊八粥 这一 天 人们还要祭祀祖先 众神并庆祝丰收 后来 逐 渐演变成吃腊八粥祝来年五谷丰登 对于腊八粥的来历说法也

记 忆 155 期 北 京 大 学 文 革 专 辑 (9) 目 录 专 稿 章 铎 从 高 云 鹏 的 遭 遇, 看 迟 群 之 流 的 专 制 附 : 高 云 鹏 给 胡 宗 式 章 铎 的 信 (2015 年 11 月 19 日 ) 评 论 马 云 龙 王 复 兴 抢 救 记 忆 : 一 个 北

硕士论文正文


不 会 忘 记, 历 史 不 会 忘 记, 当 一 个 古 老 神 州 正 以 崭 新 的 姿 态 昂 首 屹 立 于 世 界 东 方 的 时 候, 当 世 界 把 延 伸 的 广 角 镜 瞄 准 这 片 神 奇 土 地 的 时 候, 中 国 人 民 已 深 深 感 到, 现 在 所 拥 有 的,

第一章

标题

Microsoft Word - media-tips-zh.doc

A 单 位 负 责 人 B 会 计 机 构 负 责 人 C 会 计 主 管 人 员 D 会 计 人 员 多 选 题 : 1. 单 位 伪 造 变 造 会 计 凭 证 会 计 账 簿, 编 制 虚 假 财 务 会 计 报 告 的, 县 级 以 上 人 民 政 府 财 政 部 可 以 依 法 行 使 的


第六篇守势




第 二 章 鉴 证 业 务 的 定 义 和 目 标 第 五 条 鉴 证 业 务 是 指 注 册 会 计 师 对 鉴 证 对 象 信 息 提 出 结 论, 以 增 强 除 责 任 方 之 外 的 预 期 使 用 者 对 鉴 证 对 象 信 息 信 任 程 度 的 业 务 鉴 证 对 象 信 息 是 按

編 按 2

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

書本介紹


申 请 律 师 执 业 许 可 初 审 服 务 指 南 目 录 一 办 理 要 素 ( 一 ) 事 项 名 称 和 编 码 4 ( 二 ) 实 施 机 构 4 ( 三 ) 申 请 主 体 4 ( 四 ) 受 理 地 点 4 ( 五 ) 办 理 依 据 4 ( 六 ) 办 理 条 件 5 ( 七 )

环 境, 我 在 巩 固 在 校 期 间 所 学 习 的 理 论 知 识 的 同 时, 不 断 的 充 实 己, 利 用 业 余 时 间 主 动 学 习 专 业 知 识, 技 能, 把 理 论 联 系 到 工 作 实 践 中 作 为 一 名 工 作 生 活 中 的 党 员, 我 始 终 注 意 与

附件1

邻居啊 第二天 对门却悄无声息了 莫非昨夜的吵闹 仅是个幻觉 夜幕拉下时 寒风又吱溜溜地叫个不停 老婆 睡下后 我这只夜猫子 继续兴致勃勃地跟着福尔 摩斯去探案 白天的喧嚣退去了 周围格外安静 正 是读书的好时候 突然 响起了钟摆声 哒 哒 哒 节奏匀称 不疾不徐 声响却愈来愈大 格外突兀 了 原来

<4D F736F F D BAC520CAD7B6BCCAA6B7B6B4F3D1A C4EAD7A8D2B5BCBCCAF5D6B0CEF1C6C0C6B8B9A4D7F7D2E2BCFB2E646F63>

其 他 方 面 也 可 以 采 用 同 样 的 方 式, 这 样 又 可 以 锻 炼 除 语 文 方 面 的 其 他 能 力 了 而 英 语 方 面, 我 认 为 配 合 英 语 专 业 举 办 英 语 演 讲 比 赛 就 很 不 错 这 样 开 展 一 系 列 的 创 新 活 动, 锻 炼 多 方

第 六 条 办 法 第 五 条 ( 三 ) 协 会 考 评, 考 评 指 考 核 评 价 第 七 条 办 法 第 六 条 职 业 操 守 包 括 的 内 容 : 个 人 诚 信 不 做 假 账 不 偷 漏 税 不 贪 污 盗 窃 等 第 八 条 企 业 财 务 管 理 人 才 评 价 实 行 五 星

<4D F736F F D A67EABD7A4BAB3A1B1B1A8EEA8EEABD7A6DBA6E6B5FBA6F4AD70B5652E646F63>

统计工作情况汇报

他 随 身 带 有 二 三 十 张 古 方, 白 天 卖 药, 夜 晚 将 药 材 精 细 研 末, 按 方 配 制 对 于 病 人 服 药 后 反 应, 特 别 留 心 发 现 问 题, 就 近 向 老 医 生 老 药 贩 虚 心 求 教, 千 方 百 提 高 药 效 同 时 对 于 春 夏 秋

目 录 第 一 章 地 方 陪 同 导 游 人 员 服 务 程 序...1 第 一 节 地 方 陪 同 导 游 人 员 的 概 念 与 职 责...1 第 二 节 服 务 准 备...2 一 熟 悉 接 待 计 划...2 二 落 实 接 待 事 宜...5 三 物 质 和 知 识 的 准 备...

走 吧, 到 三 峡 去 : 那 里 是 我 们 先 人 用 生 命 之 血 打 造 的 家 园 走 吧, 到 三 峡 去 : 那 里 的 浪 涛 承 载 过 千 百 万 只 我 们 先 人 驶 向 今 天 的 航 船 走 吧, 到 三 峡 去 : 那 里 的 每 一 座 青 山 都 刻 满 了 我

6寸PDF生成工具

Microsoft Word - 送報伕2.doc

Microsoft Word - N011 斷翅天使

中 国 科 学 院 国 家 科 学 图 书 馆

申论写作套路万能模板

( 地 ( ) 组 织 机 构 代 码 企 业 详 细 名 称 哈 密 地 伊 吾 新 疆 广 汇 新 能 源 有 限 公 司 玛 纳 斯 玛 纳 斯 祥 云 化 纤 有 限 公 司 玛 纳 斯 玛 纳 斯 澳 洋 科 技 有 限 责

图 文 聚 焦 国 培 计 划 (2013) 甘 肃 省 农 村 小 学 音 乐 骨 干 教 师 短 期 集 中 培 训 9 月 4 日 开 班 了, 学 员 老 师 们 从 甘 肃 省 各 个 县 市 州 汇 聚 湖 南 一 师, 开 始 了 为 期 14 天 的 培 训 学 习 : 鲜 明 的

申請機構基本資料

申請機構基本資料

Microsoft Word - 三方协议书与接收函的相关说明学生版.doc

~2~

,,

untitled

櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩櫩 毧 毧 毧 毧

89SQSY.s92

精 品 库 我 们 的 都 是 精 品 _www.jingpinwenku.com 根?() A 450 B 455 C 460 D465 8, [2-(5/4*4/7+1.25*3/7)]/0.375=( ) A.2 B 1 C 0 D -1 9 甲 乙 丙 三 名 羽 毛 球 选 手 训 练 共

<4D F736F F D20A8E0B5A3C5AAB867B1D0A87CBBA1A9FAA4E2A5552E646F63>

1.3

56,,,,, :,, 1953,, 1953,1953,,1953,,,,,,,,, () ,30118, 34, ;,4912 %,5614 %, 1,1953, 1119, ,, , , 1111 (

(A) 二 小 時 (B) 三 小 時 (C) 四 小 時 (D) 五 小 時 第 一 組 出 題 6. 若 對 於 收 到 的 交 通 違 規 罰 單 不 服, 在 收 到 罰 單 幾 日 內 須 向 警 察 機 關 或 監 理 機 關 申 訴? (A) 十 天 (B) 十 五 天 (C) 二 十

大 台 北 與 桃 竹 苗 地 區 北 得 拉 曼 巨 木 步 道 新 竹 縣 尖 石 鄉 鎮 西 堡 巨 木 群 步 道 新 竹 縣 尖 石 鄉 鳥 嘴 山 登 山 步 道 苗 栗 縣 泰 安 鄉 加 里 山 登 山 步 道 苗 栗 縣 南 庄 鄉

(Microsoft Word - 3\271\375\246\321\257R.doc)


untitled

2 A

山东建筑大学学分制管理规定(试行)

数学分析(I)短课程 [Part 2] 4mm 自然数、整数和有理数



-%+!"!" # #! "# "#!!!!" # #!!!!!" # # $$%!!& ($$% )$$%(*$!!!!! +,- # # $% & $! $ & $( # # $ $ )! "# )./ $) $( $$% +,-!!!!!! $!$)(0 # #!!!! #" # # *1+

怎样使孩子更加聪明健康(五).doc

淡江大學種子課輔社台南服務隊

Microsoft Word htm

Microsoft Word - 三峽鎮衛生所_3_-張家宸.李永繁.doc

Microsoft Word - 武漢大學交流營心得_黃莉云_.doc

北京金英杰医学考试中心

Generated by Unregistered Batch DOC TO PDF Converter , please register! 浙江大学 C 程序设计及实验 试题卷 学年春季学期考试时间 : 2003 年 6 月 20 日上午 8:3

Transcription:

第 9 章 组合问题与大数运算 9.1 大数运算 在计算机中, 长整型变量的范围是 -2147483648 至 2147483647, 若用长整型变量做乘法运算, 乘积最多不能超过 10 位数 即便用双精度型 (double) 变量, 也仅能保证 16 位有效数字的精度 在某些需要更高精度的乘法运算的场合, 需要用别的办法来实现乘法运算 1. 列表法 例如, 当计 876 234 时, 把乘数与被乘数照表 9.1 列出 : 表 9.1 8 7 6 5 16 14 12 10 2 24 21 18 15 3 32 28 24 20 4 把表 9.1 中的数按图示斜线分组 ( 横纵坐标和相等的数分为一组 ), 把每组数累加起来所 得的和记在表格下方, 如表 9.2 所示 表 9.2 16 14 12 10 24 21 18 15 32 28 24 20 16 38 65 56 39 20 从最低位的 20 开始, 保留个位数字 0, 把个位以外的数 2 进到前一位 ; 把次低位的 39 加上低位进上来的 2 得 41, 保留个位数字 1, 把 4 进到前一位 ; 以此类推, 直至最高位的 16,16 加上低位进上来的 4 得 20, 保留 0, 把 2 进到最高位, 得乘积大数 2057010, 如表 9.3 所示 表 9.3 16 38 65 56 39 20 2 16+4=20 38+7=45 65+6=71 56+4=60 39+2=41 留 2 留 0 进 2 留 5 进 4 留 1 进 7 留 0 进 6 留 1 进 4 留 0 进 2 2 0 5 7 0 1 0 1

2. 程序实现根据以上思路就可以编写 C 程序了, 再经分析可得 : (1) 一个 m 位的整数与一个 位的整数相乘, 乘积为 m+-1 位或 m+ 位 (2) 程序中, 用三个字符数组分别存储乘数 被乘数与乘积 由第 (1) 步分析得知, 存放乘积的字符数组的长度应不小于存放乘数与被乘数的两个数组的长度之和 (3) 可以把第 (2) 步 计算填表 与第三 四步 累加进位 放在一起完成, 可以节省存储表格 9.2 所需的空间 (4) 程序关键部分是两层循环, 内层循环累计一组数的和, 外层循环处理保留数字与进位 程序代码如下 : #defie MAXLENGTH 1000 #iclude <stdio.h> #iclude <strig.h> void compute(char *a, char *b, char *c); void mai(void) char a[maxlength], b[maxlength], c[maxlength * 2]; puts("iput multiplier :"); gets(a); puts("iput multiplicad :"); gets(b); compute(a, b, c); puts("aswer :"); puts(c); getchar(); void compute(char *a, char *b, char *c) it i, j, m, ; log sum, carry; m=strle(a) - 1; =strle(b) - 1; for (i=m; i >=0; i--) 2

a[i] -='0'; for (i=; i >=0; i--) b[i] -='0'; c[m++2]='\0'; carry=0; for (i=m+; i >=0; i--) /* i 为坐标和 */ sum=carry; if ((j=i - m) < 0) j=0; for ( ; j<=i && j<=; j++) /* j 为纵坐标 */ sum+=a[i-j] * b[j]; /* 累计一组数的和 */ c[i+1]=sum % 10+'0'; /* 算出保留的数字 */ carry=sum / 10; /* 算出进位 */ if ((c[0]=carry+'0')=='0') /* if o carry, */ c[0]='\040'; /* c[0] equals to space */ 用以上算法计算 m 位整数乘以 位整数, 需要先进行 m 次乘法运算, 再进行约 m+ 次加法运算和 m+ 次取模运算 ( 实为整数除法 ) 把这个程序稍加修改, 让它自己产生乘数与被乘数, 然后计算随机的 7200 位整数互乘, 在 VC6.0 下耗时 4.5 s 注意以下事实 :8216547 96785 将两数从个位起, 每 3 位分为节, 列出乘法表, 将斜线 3

间的数字相加, 如表 9.4 所示 8 216 547 96 785 表 9.4 8 216 547 768 20736 52512 96 6250 169560 429395 785 768 20736 52512 6250 169560 429395 768 27016 222072 429385 将表中最后一行进行如下处理 : 从个位数开始, 每一个方格里只保留三位数字, 超出 1000 的部分进位到前一个方格里, 如表 9.5 所示 表 9.5 768 27016 222072 429385 768+27 27016+222 222072+429 取 395 进 429 =795 =27238 =222501 395 795 238 501 395 所以 8216547 96785=795238501395 也就是说在计算生成这个二维表时, 不必 1 位 1 位地乘, 而可以 3 位 3 位地乘 ; 在累加时也是满 1000 进位 这样, 计算 m 位整数乘以 位整数只需要进行 m /9 次乘法运算, 再进行约 (m+)/3 次加法运算和 (m+)/3 次取模运算 总体看来, 效率约是前一种算法的 9 倍 有人可能会想 : 既然能够 3 位 3 位地乘, 为什么不 4 位 4 位甚至 5 位 5 位地乘呢? 那不是可以提高 16 乃至 25 倍效率吗? 原因在于 : 本算法在累加表中斜线间的数字时, 如果用无符号长整数 ( 范围 0~4294967295) 作为累加变量, 在最不利的情况下 ( 两个乘数的所有数字均是 9), 能够累加约 4294967295/(999*999)=4300 次, 也就是能够准确计算任意两个均不超过 12900( 每次累加的结果 值 三位, 故 4300*3=12900) 位的整数相乘 如果 4 位 4 位地乘, 在最不利的情况下, 能够累加约 4294967295/(9999*9999)=43 次, 仅能够确保任意两个不超过 172 位的整数相乘, 没有什么实用价值, 更不要说 5 位了 程序代码如下 : #iclude<coio.h> #iclude<strig.h> #iclude<stdio.h> 4

#iclude<stdlib.h> #iclude<time.h> #defie N 7200 // 作 72xx 位的整数乘法 it max(it,it,it); it iitarray(it a[]); void write(it a[],it l); FILE *fp; void mai() it a[5000]=0,b[5000]=0,k[10001]=0; // 声明存放乘数 被乘数与积的数组 clock_t start, ed; // 声明用于计时的变量 usiged log c,d,e; // 声明作累加用的无符号长整数变量 it i,j,la,lb,ma,mi,p,q,t; // 声明其他变量 radomize(); // 初始化随机数 la=iitarray(a); // 产生被乘数, 并返回其长度 lb=iitarray(b); // 产生乘数, 并返回其长度 if(la<lb) // 如果被乘数长度小于乘数, 则交换被乘数与乘数 p=(lb>la)?lb:la; for (q=0;q<p;q++) // 交换被乘数与乘数 t=a[q],a[q]=b[q],b[q]=t; t=la,la=lb,lb=t; // 交换被乘数的长度与乘数的长度 5

start=clock();// 开始计时 c=d=0; // 清空累加变量, 其中 c 用于累加斜线间的数,d 用作进位标志 for(i=la+lb-2;i>=0;i--) // 累加斜线间的数,i 为横纵坐标之和 c=d; // 将前一位的进位标志存入累加变量 c ma=max(0,i-la+1,i-lb+1); // 求累加的下限 mi=(i>la-1)?(la-1):i; // 求累加的上限 for(j=ma;j<=mi;j++) // 计算出横纵坐标之和为 i 的单元内的数, 并累加到 c 中 c+=(log)a[j]*b[i-j]; d=c/1000; // 求进位标志 if(c>999) c%=1000; // 取 c 的末三位 k[i]=c; // 保存至表示乘积的数组 k e=k[0]+1000*d; // 求出乘积的最高位 ed=clock();// 停止计时 fp=fope("result.txt", "w+"); pritf("\the elapsed time was: %3.4f\", (ed-start)/clk_tck); // 打印消耗的时间 6

fpritf(fp,"%d",a[0]); // 打印被乘数最高位 write(a,la); // 打印被乘数其他位 fpritf(fp,"%d",b[0]); // 打印乘数最高位 write(b,lb); // 打印乘数其他位 fpritf(fp,"%ld",e); // 打印乘积最高位 write(k,la+lb-1); // 打印乘积其他位 fclose(fp); max(it a,it b,it c) it d; d=(a>b)?a:b; retur (d>c)?d:c; it iitarray(it a[]) it q,p,i; q=n+radom(100); if(q%3==0) p=q/3; else p=q/3+1; for(i=0;i<p;i++) a[i]=radom(1000); if(q%3==0) 7

a[0]=100+radom(900); if(q%3==2) a[0]=10+radom(90); if(q%3==1) a[0]=1+radom(9); retur p; void write(it a[],it l) it i; char strig[10]; for(i=1;i<l;i++) itoa(a[i],strig,10); if (strle(strig)==1) fpritf(fp,"00"); if (strle(strig)==2) fpritf(fp,"0"); fpritf(fp,"%s",strig); if((i+1)%25==0) fpritf(fp,"\"); fpritf(fp,"\"); fpritf(fp,"\"); 9.2 平面幻方 对平面幻方的构造, 分为三种情况 :N 为奇数 N 为 4 的倍数 N 为其他偶数 (4+2 的形式 ) 1. 奇数阶幻方 8

奇数阶幻方最经典的填法是罗伯特法 ( 也有人称之为楼梯方 ) 填写方法是: 把 1( 或最小的数 ) 放在第一行正中 ; 按以下规律排列剩下的 2-1 个数 : (1) 每一个数放在前一个数的右上一格 ; (2) 如果这个数所要放的格已经超出了顶行, 那么就把它放在底行, 仍然要放在右一列 ; (3) 如果这个数所要放的格已经超出了最右列那么就把它放在最左列, 仍然要放在上一行 ; (4) 如果这个数所要放的格已经超出了顶行且超出了最右列, 那么就把它放在前一个数的下一行同一列的格内 ; (5) 如果这个数所要放的格已经有数填入, 处理方法同 (4) 2. N 为 4 的倍数时互补 : 如果两个数字的和等于幻方最大数和最小数的和, 即 *+1, 称为互补 先看看 4 阶幻方的填法 : 将数字从左到右 从上到下按顺序填写 : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 将对角线上的数字, 换成与它互补的数字 这里,*+1=4*4+1=17 把 1 换成 17-1=16; 把 6 换成 17-6=11; 把 11 换成 17-11=6, 换完后就是一个四阶幻方 : 16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1 对于 =4k 阶幻方, 先把数字按顺序填写 写好后, 按 4*4 把它划分成 k*k 个方阵 因为 是 4 的倍数, 一定能用 4*4 的小方阵分割 然后把每个小方阵的对角线, 像制作 4 阶幻方的方法一样, 对角线上的数字换成互补的数字, 就构成幻方 下面是 8 阶幻方的做法 : (1) 先把数字按顺序填 然后, 按 4*4 把它分割成 2*2 个小方阵, 如表 9.6 所示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 9

(2) 每个小方阵对角线上的数字, 换成与它互补的数 表 9.6 64 2 3 61 60 6 7 57 9 55 54 12 13 51 50 16 17 47 46 20 21 43 42 24 40 26 27 37 36 30 31 33 32 34 35 29 28 38 39 25 41 23 22 44 45 19 18 48 49 15 14 52 53 11 10 56 8 58 59 5 4 62 63 1 程序代码如下 : #iclude"stdio.h" #iclude"math.h" it a[256][256]; it sum; it check(); void is(it ); mai() it i,j,,k,t,p,x; scaf("%d",&); sum=(*+1)*/2; if(%2==1)// 奇数幻方 is(); k=; if(%4==2)// 单偶数幻方 k=/2; is(k); 10

for(i=0;i<k;i++) for(j=0;j<k;j++) a[j+k]=a[j]+2*k*k; a[i+k][j]=a[j]+3*k*k; a[i+k][j+k]=a[j]+k*k; t=(-2)/4; for(i=0;i<k;i++) for(j=0;j<k;j++) if((j<t)&&(i<t)) p=a[j];a[j]=a[i+k][j];a[i+k][j]=p; if((j<t)&&(i>k-t-1)) p=a[j];a[j]=a[i+k][j];a[i+k][j]=p; if((i>=t&&i<=k-t-1)&&(j>=t&&j<t*2)) p=a[j];a[j]=a[i+k][j];a[i+k][j]=p; if(j>1&&j<=t) 11

p=a[j+k];a[j+k]=a[i+k][j+k];a[i+k][j+k]=p; if(%4==0)// 双偶数幻方 x=1; for(i=0;i<;i++) for(j=0;j<;j++) a[j]=x++; for(i=0;i<;i++) for(j=0;j<;j++) if(i%4==0&&abs(i-j)%4==0) for(k=0;k<4;k++) a[i+k][j+k]=*-a[i+k][j+k]+1; else if(i%4==3&&(i+j)%4==3) for(k=0;k<4;k++) a[i-k][j+k]=*-a[i-k][j+k]+1; if(check()==1) for(i=0;i<;i++) 12

for(j=0;j<;j++) pritf("%5d",a[j]); pritf("\"); retur ; it check(it )// 检验是否是幻方 it i,j,sum1=0,sum2; for(i=0;i<;i++) for(j=0;j<;j++) sum1+=a[j]; if(sum1!=sum) retur 0; sum1=0; for(i=0;i<;i++) for(j=0;j<;j++) sum1+=a[j]; if(sum1!=sum) retur 0; sum1=0; for(sum1=0,sum2=0,i=0,j=0;i<;i++,j++) 13

sum1+=a[j]; sum2+=a[-j-1]; if(sum1!=sum) retur 0; if(sum2!=sum) retur 0; else retur 1; void is(it )// 单偶数幻方的输入 it x,y,m; x=0;y=/2; for(m=1;m<=*;m++) a[x][y]=m; if (m%!=0) x--;y++; if(x<0) x=x+; if(y==) y=-y; else x++; if(x==) x=x-; 9.3 Catala 数 Catala 序列是一个整数序列, 其通项公式是从中取出的 C, 也叫做第 个 Catala 数, 前 几个 Catala 数是 :1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670,, 乍看之下没什么特别的, 但是 Catala 数却是许多计数问题的最终形式 14

1. Catala 数的性质 1 2 (2 )! Catala 数的基本公式 C, 0, 但是却有一些变形和具体的性质 : 1 ( 1)!! 2 2 (1) C, 0 1 这是根据原来的式子推导出来的, 推导过程如下 : 2(2 1) (2) C O 1, C 1 C 2 这个递推式可以从公式 (1) 推得 C 1 2 2 2 2 2 1 1 1 (3) C O 1, C 1 CC i i 0 i 0 2 1 (4) C 1 i 0 i 4 (5) C ~ 3 2 π 这个是 Catala 数的增长趋势 个 +1 和 个 -1 构成 2 项 : a1, a2,, a, 其和满足 a1 a2 a k 0, 0 k 2的序 列个数等于第 个 Catala 数 C 假设不满足条件的序列个数为 U, 那么就有 C 2 U 剩下的工作就是求 U 了, 假设有一个最小的 k, 令 a1 a2 a k 0 由于这里 k 是最小的, 所以必有 a1 a2 ak 1 0, a 1, 并且 k 是一个奇数 此时将前 k 项中的 +1 变为 -1, 将 -1 变为 +1, 那么就得到一 k 个有 (+1) 个 +1 和 (-1) 个 -1 的序列了, 这样的序列个数就是要求的 U, 数值大小为 2 U 1 那么就得到了 2 2 2 C U 1 2. 应用 (1) 对于任意的 k, 前 k 个元素中 -1 的个数小等于 +1 的个数的序列计数, 可以不停地 变换形式, 比如将 -1 看成右括号,+1 看成左括号, 就变成了合法括号表达式的个数 比如 2 个左括号和 2 个右括号组成的合法表达式有 C2 2 种, 是 ()() 和 (()) (2) 既然如上一点都把括号加上去了, 那么顺便就再次转换,+1 个数连乘, 乘法顺序 有 C 种, 比如三个数连乘 a*b*c, 那么等于在式子上加括号, 有 2 种乘法顺序, 分别是 (ab)c 和 a(bc) 貌似对应关系比较模糊, 取 为 3 来看看, 为 3 的时候就是 4 个数相乘了, 设为 abcd, 最初的标号定在 a 上, 对于 为 3 得到合法的括号序列有 5 个, 分别是 :((())),()(()), 15