騰訊算法題彙總[牛客網過騰訊春招題所有測試用例](下)

小Q有X首長度爲A的不同的歌和Y首長度爲B的不同的歌,現在小Q想用這些歌組成一個總長度正好爲K的歌單,每首歌最多只能在歌單中出現一次,在不考慮歌單內歌曲的先後順序的情況下,請問有多少種組成歌單的方法。

輸入描述:
每個輸入包含一個測試用例。
每個測試用例的第一行包含一個整數,表示歌單的總長度K(1<=K<=1000)。
接下來的一行包含四個正整數,分別表示歌的第一種長度A(A<=10)和數量X(X<=100)以及歌的第二種長度B(B<=10)和數量Y(Y<=100)。保證A不等於B。

輸出描述:
輸出一個整數,表示組成歌單的方法取模。因爲答案可能會很大,輸出對1000000007取模的結果。

輸入例子1:
5
2 3 3 3

輸出例子1:
9

import java.util.Scanner;

public class EatCho {

    public static void main (String[] args) {
        Scanner sc = new Scanner(System.in);
        int days = sc.nextInt();
        int count = sc.nextInt();


        if (days <= 1 || days > count){
            System.out.println(count);
            return;
        }

        //推測理想情況下,次日吃的數量都是前一天的1/2,則得到以下求第一天最大塊數公式:
        //分子爲2的n次冪
        //分母爲等比數列 a1 *(1-q的n次冪)/(1-q)
//        int high = (int)(Math.pow(2, days-1)/ (Math.pow(2, days) - 1) * count);
// 最多第一天吃的塊數(因爲測試用例太大,導致上面的數學優化不能使用,只能從count-1開始)
        int high = count-1;
        int low = 1;//最少第一天吃1塊
        int tar = high;

        //採用折半查找
        while (low <= high) {

            int mid = (low + high)/2;
            int sum = count - mid;//第二天起剩餘的塊數
            int tmp = mid;
            int i = 2;
            for (; i <= days; i++){
                tmp = (int)Math.ceil(tmp/2.0);//用於記錄今天最少吃的數量
                sum -= tmp;
                if (sum < 0){
                    //表明不夠吃了情況
                    break;
                }
            }

            if (i < days)//供過於求
                high = mid - 1;
            else {


                if (sum < 0)//供不應求
                    high = mid - 1;

                else{
                    low = mid + 1;
                    tar = mid;
                }
            }



        }

        System.out.println(tar);




    }


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