首届英才在线编程大赛-编程题回顾-java实现

参见了中华英才网的编程大赛,算法题很简单,但还是做的不熟,一道用BigInteger的没有AC

下面是三道题的题目和程序

问题1:求小于n的自然数中,17或者18的倍数和 java

有一点需要注意的是当n>17*18时,17*18只需要算一次

而且k*18>n不一定有k*17>n,所以当k*18>n后,一定要再增加k直到17*k>n

<span style="white-space:pre">	</span>public int mySum(int n) {
		if (n < 17) {
			return 0;
		}
		int res = 0;
		int k = 1;
		while (true) {
			int tmp1 = k * 17;
			int tmp2 = k++ * 18;
			if (tmp2 >= n) {
				break;
			}
			if (tmp1 % 18 != 0) {
				res += tmp1;
			}
			res += tmp2;
		}
		while (true) {
			int tmp1 = k++ * 17;
			if (tmp1 >= n) {
				break;
			}
			if (tmp1 % 18 != 0) {
				res += tmp1;
			}
		}
		return res;
	}

问题2:n*n(n<20)的正方形块,延正方形边从左上角走到右下角,一共有几种方式 java

解答:前几个比较好求n=1:2,n=2:6,n=3:20,n=4:70
可以总结为有从左上到右下一共要走2n步,其中向右或向下有n步,这样就是C2n n
中间结果很容易溢出,这样就用java的BigInteger类,理论上内存有多大,就可以计算多大的算法。
然后把公式写出来很容易发现2n*(2n-1)...*(n+1) 下面的是n*(n-1)*...*2 ,上下肯定有公因子2n,因此就减少了一次大数乘法。

	public long pathcount(int n) {
		BigInteger res1 = BigInteger.valueOf(1), res2 = BigInteger.valueOf(1);
		int i;
		if (n == 1) {
			return 2;
		}
		if (n == 2) {
			return 6;
		}
		for (i = n * 2 - 1; i > n; i--) {
			res1 = res1.multiply(BigInteger.valueOf(i));
		}
		for (i = n - 1; i > 2; i--) {
			res2 = res2.multiply(BigInteger.valueOf(i));
		}
		return res1.divide(res2).longValue();
	}

问题3:求小n的素数和  java

用到一个公式:一个非素数一定可以分解成几个素数的乘积
这样在求取答案过程中,再维护一个素数的链表,这样可以提高求素数的速度

        写博客的时候想到,没必要将素数链表遍历完,只需要遍历到sqrt(n)就可以。

	public int primesSum(int n) {
		if (n < 2) {
			return 0;
		}
		if (n == 2) {
			return 2;
		}
		List<Integer> primes = new ArrayList<Integer>();
		primes.add(2);
		int res = 2;
		for (int i = 3; i <= n; i += 2) {
			if (!divisible(i, primes)) {
				primes.add(i);
				res += i;
			}
		}
		return res;
	}

	private boolean divisible(int n, List<Integer> primes) {
		for (Integer prime : primes) {
			if (n % prime == 0) {
				return true;
			}
		}
		return false;
	}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值