codeforces problem 768B
這是第一篇博客?日志也行。。。
codeforces problem 768B
這個題做了很長時間--好幾天吧,有空的時候就想怎么做。
問題描述看 http://codeforces.com/problemset/problem/768/B
看起來是個三叉樹的題目。最開始我想用遞歸完成,遍歷每一個節點,并判斷節點是否在區間內,累加區間內的1。
但是2^50的數量級不可能在規定time和memory的情況下完成。
做了很多草稿,才逐漸明白以下幾點,
1. 只有x mod 2才會產生0, 其余葉肯定都是1,所以只用數區間[L,R]的0的個數
2. 把每一步看做三叉樹,我們只需要簡單的計算(x 循環除 2,直到結果為1)就可以知道該樹的最大層數 max
3. 三叉樹的層數肯定不會超過50,并且每一層的“中間葉節點”都是相同的(x mod 2),用數組temp記錄每一層的葉節點值
4. 第 k 層 的第 0 個葉節點左邊共有 ADL = 2^(max - k + 1)個葉節點,
5. 第 k 層 的第 0 個葉節點編號為 ADL + 1 = 2^(max - k + 1) + 1,
6. 第 k 層 的第 x 個葉節點編號為多少? 同樣可以算出來 location = (2 * x + 1) * ADL + 2 * x + 1 = (2 * x + 1) * (ADL + 1)
7. 到這一步,我們可以根據變量 k ∈ [1,max] 遍歷出每一層每一個葉節點的位置編號,判斷是否在[L,R]內,然后根據層數累加0的個數
8. 但是這樣效率仍然不高,我們實際上還是遍歷了整棵樹的一半的葉節點。 還得根據location, L, R的關系計算 x 的范圍
9. L < location < R 求出每一層的 x 的范圍,然后再累加x對應的葉節點的取值.
10. 至少做到上面這些才夠.事實上還可以優化.
11. 需要提前額外考慮初始值為0或1的情況。
Java源碼奉上,僅供參考,
import java.util.Scanner;public class Simple {public static void main(String[] args) {// TODO Auto-generated method stubScanner sc = new Scanner(System.in);long[] data = getnumber(sc.nextLine());int[] temp = new int[51];int sum = 0;int i = 1;if(data[0] == 0 || data[0] == 1){System.out.print(data[0]);}else {for (; i < temp.length; i++) {temp[i] = (int) (data[0] % 2);data[0] = data[0] / 2;if(data[0] == 1){break;}}for (int k = 1; k <= i; k++) {long add = (long) (Math.pow(2, i-k+1) - 1);long low = (data[1] - add - 1)/(2*(add + 1));long high = (data[2] - add - 1)/(2*(add + 1));for (long x = low; x <= high; x++) {long location = (2 * x + 1) * add + 2 * x + 1;if(location >= data[1] && location <= data[2]){if(temp[k] == 0){sum++;}}}}System.out.println(data[2] - data[1] - sum + 1);}}public static long[] getnumber(String temp) {String[] t = temp.split("\\s");long[] data = new long[t.length];for(int i=0;i < t.length;i++){data[i] = Long.valueOf(t[i]);}return data;}}
轉載于:https://www.cnblogs.com/weihuan098/p/6484559.html
總結
以上是生活随笔為你收集整理的codeforces problem 768B的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zbb20170228_spring_t
- 下一篇: redis 类型、方法