标题: 几道编程题
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4717
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-12-19 07:25 资料 主页 文集 短消息 看全部作者
02 太空观测

本题的两个要点在于最大公约数和长整数计算。

1.由于已知某事件在过去发生时刻 ti (1≤i≤N),因此该事件的最大正周期为 GCD(|t2-t1|, |t3-t2|, ..., |tN-t(N-1)|)。其中函数GCD(...)表示最大公约数。若 ti=t(i+1),则不参与计算。
多个数的最大公约数可以通过逐次结合运算求得:
GCD(a, b, c, d) = GCD(GCD(GCD(a,b), c), d)
因此,只要写出求两个正整数最大公约数的方法,就可以求出多个正整数的最大公约数。
以此最大公约数为周期 T ,便可求得该事件下次发生时刻为:(T - ti MOD T) MOD T

2.最大公约数求法,辗转相除法
假设算式 GCD(a,b) 中 a>b,那么使用 a MOD b 代替参数中的 a,可得到相同的结果。GCD(a,b) = GCD(a MOD b, b)
即使用参数中大数除以小数的余数代替大数,然后反复交替相除取余,直到其中一参数为0,即得到答案。

递归代码

function GCD(a, b)
    if b = 0
       return a
    else
       return GCD(b, a mod b)

非递归代码

function GCD(a, b)
    while b ≠ 0
       t := b
       b := a mod b
       a := t
    return a

3.以上 ti 及最大公约数函数的参数 a,b 都是长整数,不能使用普通的四则运算方法,只能自定义一个长整数类,然后重载各种运算操作符。
由于限制了 ti 最大值不超过 10^50,因此可以使用固定长度的结构,而不用设计动态分配内存,可以简化程序。

我的代码中,实现的方法有:
长整数输入(普通整数和字符串转化为长整数)
长整数输出(屏幕输出和长整数转化为字符串)
长整数比较(大于,小于,等于)
长整数加法(加长整数或者短整数)
长整数减法(减长整数或者短整数)
长整数乘法(乘以短整数)
长整数除法(除以长整数)
长整数取模(除以长整数)
此外,长整数除法和取模中需要用到试商函数,其目的为求出商为短整数的两个长整数相除结果,可以使用二分法实现。


顶部
性别:男-离线 周瑜

栎阳侯谏议大夫

Rank: 16
组别 翰林学士
级别 征西将军
好贴 10
功绩 943
帖子 4717
编号 1808
注册 2003-11-3
家族 瓦岗寨


发表于 2010-12-25 07:50 资料 主页 文集 短消息 看全部作者
03 主题公园

本题题意清晰,直接使用枚举法模拟游客登车过程即可得到结果,可惜这种方法复杂度太高,为O(R∙N)。
当R = 10^8,N = 10^3 时,R∙N = 10^11,超出计算范围。

本题解法可以分为两步进行优化。第一步,求出以每个小组为登车第一小组时,最后登车小组序号和总登车人数,这样,此后只需要O(1)时间即可模拟一次登车过程,复杂度降为O(R);第二步,找出是否存在周期,并根据登车周期求出结果,复杂度进一步降为O(N)。

一、先来看第一步,可以有O(N^2),O(NlogN),O(N)多种方法。

1. 每次登车组数不会超过 N 组,因此直接使用枚举法模拟登车过程,复杂度为O(N^2)。

2. O(NlogN)算法:
把 g 数组复制一遍,附在原数组后面,即:
g[N...2N-1] = g[0...N-1]
定义 S[i] 为 g 数组前 i 项之和,则 S 为递增数组
S[0] = 0
S[i] = S[i-1] + g[i-1]
计算以每组起始登车时可装载的最后一组时,可在 S[i] 到 S[i+N] 之间使用二分法,最后一个不大于 S[i]+k 的项即为最后上车的一组。

3. O(N)算法:
双指针法。第一个指针指向每次登车的第一组,第二个指针指向可装载的最后一组。每当第一个指针向后挪时,第二个指针或者停留原地,或者向后挪动一位或多位。因此,第二个指针不可能反向向前挪动。
第一个指针最多挪动 N 位,第二个指针最多挪动 2N-1 位,因此这复杂度为 O(N)。

二、寻找周期。
所谓周期,指的是从某时刻起,在过山车运行一次或多次后,原来首先登车的一组再次首先登车,此后所有登车情况完全与上一周期相同。
根据鸽巢原理,当运行次数 R 大于游客组数 N 时,周期必然存在。

若 R≤N,可直接得到结果。
若 R>N,可以模拟前 N+1 次登车过程,找出周期长度和开始位置,并求出周期数。

总登车人数 = 周期前登车人数 + 每周期登车人数*周期数 + 周期后登车人数

由于周期长度及周期前、周期后的运行次数均不大于 N,因此这一步和总的算法复杂度也为 O(N)。

[color=Silver][[i] 本帖最后由 周瑜 于 2010-12-25 12:36 编辑 [/i]][/color]


顶部

正在浏览此帖的会员 - 共 1 人在线




当前时区 GMT+8, 现在时间是 2025-8-16 08:24
京ICP备2023018092号 轩辕春秋 2003-2023 www.xycq.org.cn

Powered by Discuz! 5.0.0 2001-2006 Comsenz Inc.
Processed in 0.010361 second(s), 9 queries , Gzip enabled

清除 Cookies - 联系我们 - 轩辕春秋 - Archiver - WAP