(ACM系列之一)从简单开始

本人冒着被投新手帖或隐藏帖的危险,预备在本论坛持续发布一个ACM算法题Java版的帖子。

我只有一个简单的目的,让“爱思考、爱编程”成为一种习惯。

当然不能只有代码的堆砌。很多大师和专家在研究设计模式、算法和很多Java的基础,关于面向对象、性能、并发和各种开源项目的帖子层出不穷,小弟也在此论坛受益菲浅。本着“你快乐,我快乐,大家快乐”的原则,小弟的帖子开始出现了。若有不当,可投新手或隐藏,论坛积分已是浮云,“失去的一定能找回来”。

做一件事情当然需要从简单的开始,循序渐进。所谓“欲速则不达,贪多嚼不烂”啊!!

此贴是第一帖,下面进入正题:

题目是这样的:

A number sequence is defined as follows:

f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.

Given A, B, and n, you are to calculate the value of f(n).


这几个简单的单词我就不翻译了。我主要说说我的解法。

对于这个题,我相信给许许多多的程序员的第一印象就是递归。递归是一个伟大的发明,是一种美丽的思想。生活中处处有递归。

不过在java中,递归也有危险。对海量数据而言,递归会造成java对内存溢出,我刚学编程那会儿,可是遇到过不少。

对于这道题而言,是需要先分析的。这是一道简单的概率题(我知道,我知道,新手帖嘛。。)

仔细观察,就会发现,这道题的规律,当然是除了递归性质之后的规律。

首先,f(1) = 1,f(2) = 1。这个是前提,在代码中体现在if判断中。

最重要的是第三个式子,f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7。(mod翻译成java语言为%)

首先,我们会发现f(n)的取值范围为0-6,且未等概率的。同样f(n-1)与f(n-2)的取值范围也为0-6,同样为等概率的。

其次,我们可以认为f(n)是由f(n-1)与f(n-2)组合而成的,A和B是常量,f(n-1)与f(n-2)的取值范围确定,且为等概率事件,那么就有7*7=49种结果。那么我的思想就是重复计算(我知道这不是最好的算法,这也是我发帖来讨论的原因),还是利用递归思想,循环计算M次,而M = n % 49。即去总次数去掉重复结果计算后的次数。

在代码中,我用left代替了A * f(n - 1),用right代替了B * f(n - 2)。

现在,就可以上代码了。

package org.fantasizer.algorithms.acm.p1005;

public class Main {
public static void main(String[] args) {
System.out.println(calculate(1, 1, 3));
System.out.println(calculate(1, 2, 10));
System.out.println(calculate(1, 2, 100000000));
}

public static long calculate(int A, int B, int n) {
if (n == 1 || n == 2) {
return 1;
}

long left = 1;
long right = 1;

long result = 0;
for (int i = 2; i < n % 49; i++) {
result = (A * left + B * right) % 7;
right = left;
left = result;
}
return result;
}
}



最后说一下,讨论是用来学习的一种很好的方式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值