首屆英才在線編程大賽-編程題回顧-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;
	}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章