1. 程式人生 > 其它 >藍橋杯 楊輝三角

藍橋杯 楊輝三角

轉載大佬的連結

import java.util.*;
public class Main {
	/**
	 * 組合數和楊輝三角:第i行第j列的數都是組合數C(i, j) (i,j從0開始)
        C(n, 1) = n --> 對應從左向右看斜著的第二列! ---> 一定有解
    由於楊輝三角左右對稱(C(a, b) == C(a, a-b)),又由於找第一次出現,因此一定在左邊,右邊可以直接刪掉!
            			1  ---> C(0, 0)
          			  1 
        			1   2  ---> C(2, 1)
      			  1   3                             ---> C(2n, n)
    			1   4   6  ---> C(4, 2)
  			  1   5   10
			1   6   15  20 ---> C(6, 3)
    n最大1e9, C(34, 17) > 1e9, C(32, 16) < 1e9,因此只要列舉前16個斜行即可 
	 * */
	
	// C(a, b) = a!/(b!(a-b)!) = a * (a-1) .. b / b!
	public static long C(long a,long b,long n) {
		long res = 1;
		for(long i=a,j=1;j<=b;i--,j++) {
			//階乘計算
			//得到組合數
			res = res * i / j;
			if(res > n) return res;
			//如果計算結果大於自己之前輸入的數字 那麼就停止
		}
		return res;
		//返回結果
	}
	 public static boolean check(long k,long n) {
		//找左邊界 因為需要找第一次出現,所以是左邊界模板
		 //此處是二分模板
		 // l 是斜線右上角的行數 r 是斜線左下角的行數
		long l = 2 * k, r = Math.max(n, l);
		while(l<r) {
			long mid = (l+r)/2;
			if(C(mid,k,n)>=n) r=mid;
			else l = mid + 1;
		}
		//判斷找到的值不是與之前輸入的值相等
		if(C(r,k,n)!=n) {
			return false;
		}
		//找到的值 那麼根據公式返回第一次出現的位置
		//組合數公式
		System.out.print((r+1)*r/2+k+1);
		return true;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader =new Scanner(System.in);
		long n=reader.nextLong();
		for(long k=16;;k--) {
			//找到數 則停止
			if(check(k,n)) break;
		}
	}
 
}