主頁 > 後端開發 > 第十二屆藍橋杯 2021年國賽真題 (Java 大學B組)

第十二屆藍橋杯 2021年國賽真題 (Java 大學B組)

2021-10-21 07:55:08 後端開發

藍橋杯 2021年國賽真題(Java 大學 B 組 )

  • #A 整數范圍
  • #B 純質數
    • 預備知識
    • 樸素解法
    • 按位列舉
  • #C 完全日期
    • Java黨的完全勝利
    • 樸素解法
    • 樸素改進
    • 不依賴 API 的實作
  • #D 最小權值
    • 記憶化搜索
    • 動態規劃
  • #E 大寫
  • #F 123
    • 前綴和
  • #G 和與乘積
    • 優雅騙分
  • #H 巧克力
    • 貪心演算法
    • 并查集優化
    • 貪心 + 大根堆
  • #I 翻轉括號序列
    • 線段樹
  • #J 異或三角
    • 線性遞推
    • 數位DP


認真整下,不嘻嘻哈哈了,


#A 整數范圍

本題總分:5 分


問題描述

??用 8 8 8 位二進制(一個位元組)來表示一個非負整數,表示的最小值是 0 0 0,則一般能表示的最大值是多少?


答案提交

??這是一道結果填空的題,你只需要算出結果后提交即可,本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分,


255

calcCode:

public class Test {

    public static void main(String[] args) {
        System.out.print(0xFF);
    }
}

?


#B 純質數

本題總分:5 分


問題描述

??如果一個正整數只有 1 1 1 和它本身兩個約數,則稱為一個質數(又稱素數),
??前幾個質數是: 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 , ? ? ? 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, · · · 2,3,5,7,11,13,17,19,23,29,31,37,???
??如果一個質數的所有十進制數位都是質數,我們稱它為純質數,例如: 2 , 3 , 5 , 7 , 23 , 37 2, 3, 5, 7, 23, 37 2,3,5,7,23,37 都是純質數,而 11 , 13 , 17 , 19 , 29 , 31 11, 13, 17, 19, 29, 31 11,13,17,19,29,31 不是純質數,當然 1 , 4 , 35 1, 4, 35 1,4,35 也不是純質數,
??請問,在 1 1 1 20210605 20210605 20210605 中,有多少個純質數?


答案提交

??這是一道結果填空的題,你只需要算出結果后提交即可,本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分,


1903


預備知識


??如果不會一種合數篩法的,估計跑到比賽結束結果都出不來,

??質數打表,

??就是為了這點題解,

??我才寫的這篇博客,

??就是為了這篇博客,

??我才立的這個標題,


樸素解法


??一種樸素的想法,在打表 [ 1 , 20210605 ] [1,20210605] [1,20210605] 間的質數時,額外的進行一次純質數效驗,并將結果累加起來,

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static final int N = 20210605;

    public static void main(String[] args) {
        boolean[] marked = new boolean[N + 1];
        List<Integer> primes = new ArrayList();
        marked[0] = marked[1] = true;
        int ans = 0;
        for (int i = 2; i <= N; i++) {
            if (!marked[i]) {
                primes.add(i);
                boolean flag = false;
                for (int k = i; k > 0; k /= 10)
                    if (flag = marked[k % 10]) break;
                if (!flag) ans++;
            }
            for (int p : primes) {
                if (p * i > N)  break;
                marked[p * i] = true;
                if (i % p == 0) break;
            }
        }
        System.out.println(ans);
    }
}


按位列舉


??在樸素的解法中,我們會發現,很多拆分判斷一個質數是否是純質數是沒有必要的,因為在 [ 0 , 10 ) [0,10) [0,10) 中,質數僅占 { 2 , 3 , 5 , 7 } \{2,3,5,7\} {2,3,5,7} 四位,如果僅判斷這四個數字組合成的數是否是質數的話,性能能否有進一步的提升呢?

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {

    public static final int N = 20210605;

    public static int[][] digits = new int[8][4];

    public static void main(String[] args) {
        boolean[] primes = new boolean[N + 1];
        List<Integer> helper = new ArrayList();
        Arrays.fill(primes, 2, N, true);
        int ans = 0;
        for (int i = 2; i <= N; i++) {
            if (primes[i]) helper.add(i);
            for (int p : helper) {
                if (p * i > N)  break;
                primes[p * i] = false;
                if (i % p == 0) break;
            }
        }
        digits[0] = new int[]{2, 3, 5, 7};
        for (int k = 1; k < 7; k++)
            for (int i = 0; i < 4; i++)
                digits[k][i] = digits[k - 1][i] * 10;
        digits[7] = new int[]{ digits[6][0] * 10 };
        System.out.println(dfs(primes, 0, 0));
    }

    public static int dfs(boolean[] primes, int k, int depth) {
        if (depth == 8) return k <= N && primes[k] ? 1 : 0;
        int ans = primes[k] ? 1 : 0;
        for (int a : digits[depth])
            ans += dfs(primes, k + a, depth + 1);
        return ans;
    }
}

??實際上性能并沒有進一步的提升,并且代碼量還有所增加,

??這是因為在 ( 1 , N ] (1,N] (1,N] 這個范圍中的質數大約有 N ln ? N \cfrac{N}{\ln N} lnNN? 個,而按位組成的可能是純質數的數大約有 4 ln ? N 4^{\ln N} 4lnN 個,這顯然不是一個增值量級的,

??但這里放這么一段代碼,是為了進一步擴展刷題較少的讀者的解題思路,能掌握一種方法來解決其他的問題,


#C 完全日期

本題總分:10 分


問題描述

??如果一個日期中年月日的各位數字之和是完全平方數,則稱為一個完全日期,
??例如: 2021 2021 2021 6 6 6 5 5 5 日的各位數字之和為 2 + 0 + 2 + 1 + 6 + 5 = 16 2 + 0 + 2 + 1 + 6 + 5 = 16 2+0+2+1+6+5=16,而 16 16 16 是一個完全平方數,它是 4 4 4 的平方,所以 2021 2021 2021 6 6 6 5 5 5 日是一個完全日期,
??例如: 2021 2021 2021 6 6 6 23 23 23 日的各位數字之和為 2 + 0 + 2 + 1 + 6 + 2 + 3 = 16 2 + 0 + 2 + 1 + 6 + 2 + 3 = 16 2+0+2+1+6+2+3=16,是一個完全平方數,所以 2021 2021 2021 6 6 6 23 23 23 日也是一個完全日期,
??請問,從 2001 2001 2001 1 1 1 1 1 1 日到 2021 2021 2021 12 12 12 31 31 31 日中,一共有多少個完全日期?


答案提交

??這是一道結果填空的題,你只需要算出結果后提交即可,本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分,


977


Java黨的完全勝利


??LocalDate好用,


樸素解法


??列舉 [ 2001 [2001 [2001- 01 01 01- 01 01 01 2021 2021 2021- 12 12 12- 31 ] 31] 31] 這個區間間內的時間,判斷然后累加,

import java.time.LocalDate;

public class Test {

    public static final int maxPerfect = 2 + 0 + 1 + 9 + 0 + 9 + 2 + 9;

    public static final boolean[] perfect = new boolean[maxPerfect + 1];

    public static LocalDate start = LocalDate.of(2001, 01, 01);

    public static LocalDate end = LocalDate.of(2021, 12, 31);

    public static void main(String[] args) {
        int count = 0;
        for (int i = 1; i * i<= maxPerfect; i++)
            perfect[i * i] = true;
        while (end.compareTo(start) >= 0) {
            if (perfect[calc(start)])
                count++;
            start = start.plusDays(1);
        }
        System.out.println(count);
    }

    public static int calc(LocalDate date) {
        String dateStr = date.toString();
        int res = 0;
        for (int i = dateStr.length() - 1; i >= 0; i--)
            if (Character.isDigit(dateStr.charAt(i)))
                res += Character.digit(dateStr.charAt(i), 10);
        return res;
    }
}

樸素改進


??在 [ 2001 [2001 [2001- 01 01 01- 01 01 01 2021 2021 2021- 12 12 12- 31 ] 31] 31] 中,各數位之和不僅存在最大值 2 + 0 + 1 + 9 + 0 + 9 + 2 + 9 = 32 2 + 0 + 1 + 9 + 0 + 9 + 2 + 9 = 32 2+0+1+9+0+9+2+9=32,還存在有最小值 2 + 0 + 0 + 1 + 0 + 1 + 0 + 1 2 + 0 + 0 + 1 + 0 + 1 + 0 + 1 2+0+0+1+0+1+0+1,也就是說,可能的完全平方數,不外乎 3 × 3 3 × 3 3×3 4 × 4 4 × 4 4×4 5 × 5 5 × 5 5×5 三個,就這一點我們來簡化我們的代碼,

import java.time.LocalDate;

public class Test {

    public static LocalDate start = LocalDate.of(2001, 01, 01);

    public static LocalDate end = LocalDate.of(2021, 12, 31);

    public static void main(String[] args) {
        int count = 0;
        while (end.compareTo(start) >= 0) {
            if (isPerfect(start)) count++;
            start = start.plusDays(1);
        }
        System.out.println(count);
    }

    public static boolean isPerfect(LocalDate date) {
        String dateStr = date.toString();
        int sum = 0;
        for (int i = dateStr.length() - 1; i >= 0; i--)
            if (Character.isDigit(dateStr.charAt(i)))
                sum += Character.digit(dateStr.charAt(i), 10);
        return sum == 3 * 3 || sum == 4 * 4 || sum == 5 * 5;
    }
}

不依賴 API 的實作


??先統計出平年月份和日期各數位之和的出現次數,然后遍歷年份時額外的判斷一道是否為閏年,

public class Test {

    public static void main(String[] args) {
        int[] bigMonth = { 1, 3, 5, 7, 8, 1 + 0, 1 + 2 };
        int[] smallMonth = { 4, 6, 9, 1 + 1 };
        int[] calendar = new int[9 + 2 + 9 + 1];
        int ans = 0;
        for (int day = 1; day <= 31; day++)
            for (int month : bigMonth)
                calendar[month + calc(day)]++;
        for (int day = 1; day <= 30; day++)
            for (int month : smallMonth)
                calendar[month + calc(day)]++;
        for (int day = 1; day <= 28; day++)
            calendar[2 + calc(day)]++;
        for (int year = 2001; year <= 2021; year++) {
            if (isLeapYear(year))
                if (isLeapYear(year + 2 + 2 + 9)) ans++;
            for (int i = 0; i < calendar.length; i++) {
                if (calendar[i] == 0) continue;
                if (isPerfect(calc(year) + i))
                    ans += calendar[i];
            }
        }
        System.out.println(ans);
    }

    public static int calc(int n) {
        int res = 0;
        do
            res += n % 10;
        while ((n /= 10) > 0);
        return res;
    }

    public static boolean isPerfect(int num) { return num == 3 * 3 || num == 4 * 4 || num == 5 * 5; }

    public static boolean isLeapYear(int year) { return year % 100 == 0 ? year % 400 == 0 : year % 4 == 0; }
}

#D 最小權值

本題總分:10 分


問題描述

??對于一棵有根二叉樹 T T T,小藍定義這棵樹中結點的權值 W ( T ) W(T) W(T) 如下:
??空子樹的權值為 0 0 0
??如果一個結點 v v v 有左子樹 L L L, 右子樹 R R R,分別有 C ( L ) C(L) C(L) C ( R ) C(R) C(R) 個結點,則 W ( v ) = 1 + 2 W ( L ) + 3 W ( R ) + ( C ( L ) ) 2 C ( R ) W(v) = 1 + 2W(L) + 3W(R) + (C(L))^{2} C(R) W(v)=1+2W(L)+3W(R)+(C(L))2C(R)
??樹的權值定義為樹的根結點的權值,
??小藍想知道,對于一棵有 2021 2021 2021 個結點的二叉樹,樹的權值最小可能是多少?


答案提交

??這是一道結果填空的題,你只需要算出結果后提交即可,本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分,


2653631372


記憶化搜索


那可真蠢

這題就是把動規兩個字放在了題面上,沒什么好說的,

public class Test {

    public static final int N = 2021;

    public static long[] map = new long[N + 1];

    public static void main(String[] args) { System.out.println(dfs(N)); }

    public static long dfs(int TSize) {
        if (TSize == 0 || map[TSize] != 0) return map[TSize];
        long TWeight = Long.MAX_VALUE;
        for (int LC = 0; LC < TSize; LC++) {
            int RC = TSize - LC - 1;
            long weight =
                1 + 2 * dfs(LC) + 3 * dfs(RC) +  LC * LC * RC;
            TWeight = Math.min(TWeight, weight);
        }
        return map[TSize] = TWeight;
    }
}

動態規劃


??根據題意,顯然有 N = 2021 N = 2021 N=2021 W ( 0 ) = 0 W(0) = 0 W(0)=0 W ( N ) = min ? { 1 + 2 W ( L ) + 3 W ( R ) + ( C ( L ) ) 2 C ( R ) } W(N) = \min \{1 + 2W(L) + 3W(R) + (C(L))^{2}C(R)\} W(N)=min{1+2W(L)+3W(R)+(C(L))2C(R)},其中 L + R = N ? 1 L + R = N - 1 L+R=N?1 0 ≤ L ≤ R ≤ N 0 \leq L \leq R \leq N 0LRN

??狀態轉移方程就在臉上: d p ( y ) = { 0 i = 0 min ? { 1 + 2 d p ( l ) + 3 d p ( r ) + l 2 r } l + r = i ? 1 , 0 ≤ l ≤ r ≤ i dp(y)=\left\{ \begin{array}{lr} 0&i = 0\\ \min \{1 + 2dp(l) + 3dp(r) + l^{2}r\}&l + r = i - 1,0 \leq l \leq r \leq i \end{array} \right. dp(y)={0min{1+2dp(l)+3dp(r)+l2r}?i=0l+r=i?10lri???懂得都懂,

public class Test {

    public static final int N = 2021;

    public static void main(String[] args) {
        long[] dp = new long[N + 1];
        for (int i = 1; i <= N; i++) {
            dp[i] = Long.MAX_VALUE;
            for (int l = i >> 1; l >= 0; l--)
                dp[i] = Math.min(dp[i],
                    1 + 2 * dp[l] + 3 * dp[i - l - 1] + l * l * (i - l - 1));
        }
        System.out.println(dp[N]);
    }
}

#E 大寫

時間限制: 1.0 1.0 1.0s 記憶體限制: 512.0 512.0 512.0MB 本題總分: 15 15 15


問題描述

??給定一個只包含大寫字母和小寫字母的字串,請將其中所有的小寫字母轉換成大寫字母后將字串輸出,


輸入格式

??輸入一行包含一個字串,


輸出格式

??輸出轉換成大寫后的字串,


測驗樣例1

Input:
LanQiao

Output:
LANQIAO

評測用例規模與約定

??對于所有評測用例,字串的長度不超過 100 100 100


code:

public class Main {

    public static void main(String[] args) {
        System.out.println(new java.util.Scanner(System.in).next().toUpperCase());
    }
}

送分,


#F 123

時間限制: 5.0 5.0 5.0s 記憶體限制: 512.0 512.0 512.0MB 本題總分: 15 15 15


問題描述

??小藍發現了一個有趣的數列,這個數列的前幾項如下:
?? 1 , 1 , 2 , 1 , 2 , 3 , 1 , 2 , 3 , 4 , . . . 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, ... 1,1,2,1,2,3,1,2,3,4,...
??小藍發現,這個數列前 1 1 1 項是整數 1 1 1,接下來 2 2 2 項是整數 1 1 1 2 2 2,接下來 3 3 3 項是整數 1 1 1 3 3 3,接下來 4 4 4 項是整數 1 1 1 4 4 4,依次類推,
??小藍想知道,這個數列中,連續一段的和是多少,


輸入格式

??輸入的第一行包含一個整數 T T T,表示詢問的個數,
??接下來 T T T 行,每行包含一組詢問,其中第 i i i 行包含兩個整數 l i l_{i} li? r i r_{i} ri?,表示詢問數列中第 l i l_{i} li? 個數到第 r i r_{i} ri? 個數的和,


輸出格式

??輸出 T T T 行,每行包含一個整數表示對應詢問的答案,


測驗樣例1

Input:
3
1 1
1 3
5 8

Output:
1
4
8

評測用例規模與約定

??對于 10 10 10% 的評測用例, 1 ≤ T ≤ 30 , 1 ≤ l i ≤ r i ≤ 100 1 \leq T \leq 30, 1 \leq l_{i} \leq r_{i} ≤ 100 1T30,1li?ri?100
??對于 20 20 20% 的評測用例, 1 ≤ T ≤ 100 , 1 ≤ l i ≤ r i ≤ 1000 1 \leq T \leq 100, 1 \leq l_{i} \leq r_{i} ≤ 1000 1T100,1li?ri?1000
??對于 40 40 40% 的評測用例, 1 ≤ T ≤ 1000 , 1 ≤ l i ≤ r i ≤ 1 0 6 1 \leq T \leq 1000, 1 \leq l_{i} \leq r_{i} ≤ 10^{6} 1T1000,1li?ri?106
??對于 70 70 70% 的評測用例, 1 ≤ T ≤ 10000 , 1 ≤ l i ≤ r i ≤ 1 0 9 1 \leq T \leq 10000, 1 \leq l_{i} \leq r_{i} ≤ 10^{9} 1T10000,1li?ri?109
??對于 80 80 80% 的評測用例, 1 ≤ T ≤ 1000 , 1 ≤ l i ≤ r i ≤ 1 0 12 1 \leq T \leq 1000, 1 \leq l_{i} \leq r_{i} ≤ 10^{12} 1T1000,1li?ri?1012
??對于 90 90 90% 的評測用例, 1 ≤ T ≤ 10000 , 1 ≤ l i ≤ r i ≤ 1 0 12 1 \leq T \leq 10000, 1 \leq l_{i} \leq r_{i} ≤ 10^{12} 1T10000,1li?ri?1012
??對于所有評測用例, 1 ≤ T ≤ 100000 , 1 ≤ l i ≤ r i ≤ 1 0 12 1 \leq T \leq 100000, 1 \leq l_{i} \leq r_{i} ≤ 10^{12} 1T100000,1li?ri?1012


前綴和


??區間和問題,一般先考慮的都是使用前綴和,但這里給出的區間范圍太大,以至于用全部的記憶體來存放前綴和,能通過的用例可能也只有半數,因此這里要將原序列 [ 1 , 1 , 2 , 1 , 2 , 3 , 1 , ? ? , n ? 1 , n ] \pmb[1,1,2,1,2,3,1,\ \cdots,n-1,n\pmb] [?[??[1,1,2,1,2,3,1, ?,n?1,n]?]??]變形為矩陣 [ 1 1 2 1 2 3 ? ? ? ? 1 2 3 ? n ] \begin{bmatrix}1\\1&2\\1&2&3\\\vdots&\vdots&\vdots&\ddots\\1&2&3&\cdots&n\end{bmatrix} ????????111?1?22?2?3?3????n?????????為了能涵蓋 [ 1 , 1 0 12 ] [1,10^{12}] [1,1012] 間的查詢,即矩陣包含 1 0 12 10^{12} 1012 個元素,這里 n n n n = 2 E 12 n = \sqrt{2E12} n=2E12 ?

??對于序列變形的矩陣,我們分別求出列與最后一行的前綴和后,組合起來就能在對數時間內 (需要二分查找給定 k 所在的行) 得到任意 [ 1 , k ] [1,k] [1,k] k ∈ [ 1 , 1 0 12 ] k \in [1,10^{12}] k[11012] 間內的元素和,對于任意 ∑ i = l r a i \sum_{i = l}^{r} a_{i} i=lr?ai?,我們只需轉換為 ∑ i = 1 r a i ? ∑ i = 1 l ? 1 a i \sum_{i = 1}^{r} a_{i} - \sum_{i = 1}^{l - 1} a_{i} i=1r?ai??i=1l?1?ai? 問題就被解決了,

??還有就是溢位問題,形如這種矩陣,在最大元素為 n n n 時,其矩陣元素和為 n + 2 ( n ? 1 ) + 3 ( n ? 2 ) + ? + n n + 2(n - 1) + 3(n - 2) + \cdots + n n+2(n?1)+3(n?2)+?+n
?? = n ( 1 + 2 + 3 + ? + n ) ? n ( 1 × 2 + 2 × 3 + 3 × 4 + ? + ( n ? 1 ) n ) =n(1 +2+3+\cdots+n)-n(1×2+2×3+3×4+\cdots+(n - 1)n) =n(1+2+3+?+n)?n(1×2+2×3+3×4+?+(n?1)n)
?? = n 2 ( n ? 1 ) 2 ? ( 1 2 + 1 + 2 2 + 2 + 3 2 + ? + ( n ? 1 ) 2 + n ? 1 ) =\cfrac{n^{2}(n-1)}{2} - (1^2+1 + 2^2 + 2 + 3^2 +\cdots +(n - 1)^2 + n - 1) =2n2(n?1)??(12+1+22+2+32+?+(n?1)2+n?1)
?? = n 2 ( n ? 1 ) 2 ? { ( 1 2 + 2 2 + 3 2 + ? + ( n ? 1 ) 2 ) + ( 1 + 2 + 3 + ? + n ? 1 ) } =\cfrac{n^{2}(n-1)}{2} - \{(1^2 + 2^2 + 3^2 +\cdots +(n - 1)^2) + (1 + 2 + 3 + \cdots + n - 1)\} =2n2(n?1)??{(12+22+32+?+(n?1)2)+(1+2+3+?+n?1)}
?? = n 2 ( n ? 1 ) 2 ? n ( n ? 1 ) ( 2 n ? 1 ) 6 ? n ( n ? 1 ) 2 =\cfrac{n^{2}(n-1)}{2} - \cfrac{n(n - 1)(2n - 1)}{6}-\cfrac{n(n-1)}{2} =2n2(n?1)??6n(n?1)(2n?1)??2n(n?1)?

??取 n n n 2 E 12 \sqrt{2E12} 2E12 ?,矩陣元素和約為 4.7 E 17 4.7E17 4.7E17,長整形夠用,


code:

import java.io.*;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) { new Main().run(); }

    int N = (int)Math.sqrt(2E12) + 1;
    long[] row = new long[N + 1], col = new long[N + 1];

    void run() {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        for (int i = 1; i <= N; i++) {
            row[i] = i + row[i - 1];
            col[i] = col[i - 1] + row[i];
        }
        int T = in.readInt();
        long l, r;
        while (T-- > 0) {
            l = in.readLong();
            r = in.readLong();
            out.println(sum(r) - sum(l - 1));
        }
        out.flush();
    }

    long sum(long r) {
        int k = lowerBound(r);
        return r == row[k] ? col[k] : col[k - 1] + row[(int)(r - row[k - 1])];
    }

    int lowerBound(long k) {
        int offset = 0, length = N + 1;
        while (length > 0) {
            int half = length >> 1;
            if (k > row[offset + half]) {
                offset += half + 1;
                length -= half + 1;
            } else length = half;
        }
        return offset;
    }

    class InputReader {

        BufferedReader reader;
        StringTokenizer token;

        InputReader(InputStream in) {
            this.reader = new BufferedReader(new InputStreamReader(in));
        }

        String read() {
            while (token == null || !token.hasMoreTokens()) {
                try {
                    token = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return token.nextToken();
        }

        int readInt() { return Integer.parseInt(read()); }

        long readLong() { return Long.parseLong(read()); }
    }
}


#G 和與乘積

時間限制: 1.0 1.0 1.0s 記憶體限制: 512.0 512.0 512.0MB 本題總分: 20 20 20


問題描述

??給定一個數列 A = ( a 1 , a 2 , ? ? , a n ) A = (a_{1}, a_{2}, \cdots, a_{n}) A=(a1?,a2?,?,an?),問有多少個區間 [ L , R ] [L, R] [L,R] 滿足區間內元素的乘積等于他們的和,即 a L ? a L + 1 ? ? a R = a L + a L + 1 + ? + a R a_{L} · a_{L+1} \cdots · a_{R} = a_{L} + a_{L+1} + \cdots + a_{R} aL??aL+1???aR?=aL?+aL+1?+?+aR?


輸入格式

??輸入第一行包含一個整數 n n n,表示數列的長度,
??第二行包含 n n n 個整數,依次表示數列中的數 a 1 , a 2 , ? ? , a n a_{1}, a_{2}, \cdots, a_{n} a1?,a2?,?,an?


輸出格式

??輸出僅一行,包含一個整數表示滿足如上條件的區間的個數,


測驗樣例1

Input:
4
1 3 2 2

Output:
6

Explanation:
符合條件的區間為 [1, 1], [1, 3], [2, 2], [3, 3], [3, 4], [4, 4],

評測用例規模與約定

??對于 20 20 20% 的評測用例, n ≤ 3000 n \leq 3000 n3000
??對于 50 50 50% 的評測用例, n ≤ 20000 n \leq 20000 n20000
??對于所有評測用例, 1 ≤ n ≤ 200000 , 1 ≤ a i ≤ 200000 1 \leq n \leq 200000, 1 \leq ai \leq 200000 1n200000,1ai200000


優雅騙分


??推了一天,啥也沒推出來,放棄了,

??面對這種樸素思路復雜度在 O ( n 2 ) O(n^{2}) O(n2) 的問題,我們可以選擇一個不可能的元素將其折半,假設這個元素在序列的第 m m m 個,折半后的復雜度就在 O ( m 2 + ( n ? m ) 2 ) O(m^{2} + (n - m)^{2}) O(m2+(n?m)2)

??理論上, m m m 越小且每個點分布的越均勻,那么安裝這種方法拆分,復雜度可以將至 O ( n log ? n ) O(n \log n) O(nlogn) 甚至 O ( n ) O(n) O(n)

??在 a L ? a L + 1 ? ? a R = a L + a L + 1 + ? + a R a_{L} · a_{L+1} \cdots · a_{R} = a_{L} + a_{L+1} + \cdots + a_{R} aL??aL+1???aR?=aL?+aL+1?+?+aR? 這個運算式中,若 R ? L > 1 R - L >1 R?L>1 的情況,兩邊必為合數,

??如果任意 a L ? a L + 1 ? ? a R a_{L} · a_{L+1} \cdots · a_{R} aL??aL+1???aR? 中存在一個較大的質數 p p p,那么有極大的可能 a L + a L + 1 + ? + a R a_{L} + a_{L+1} + \cdots + a_{R} aL?+aL+1?+?+aR? 不能將其整除,也就是任給若干個 ( 0 , 2 × 1 0 5 ] (0,2×10^{5}] (0,2×105] 間的自然數,他們的和 p p p 的和是 p p p 的倍數概率,

??不會算,反正很低就對了,我們可以根據此將原序列分成期望若干個互不干涉的子序列,

??運氣好就A了,


import java.io.*;
import java.util.List;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) { new Main().run(); }

    final int N = 200000, p = 131;

    void run() {
        InputReader in = new InputReader(System.in);
        int n = in.readInt(), ans = n;
        int[] A = new int[n];
        for (int i = 0; i < n; i++)
            A[i] = in.readInt();
        if (n > 0xC60) {
            boolean[] compos = new boolean[N + 1];
            List<Integer> prime = new ArrayList();
            compos[1] = true;
            for (int i = 2; i <= N; i++) {
                if (!compos[i]) prime.add(i);
                for (int p : prime) {
                    if (p * i > n) break;
                    compos[p * i] = true;
                    if (i % p == 0)break;
                }
            }
            for (int i = 0, j = 0; i < n; i = j++) {
                while (j < n && (compos[A[i]] || A[i] >= p)) j++;
                ans += calc(A, i, j - i);
            }
        } else ans += calc(A, 0, n);
        System.out.println(ans);
    }

    int calc(int[] A, int offset, int length) {
        int ans = 0;
        long sum, product;
        for (int i = 0; i < length; i++) {
            sum = product = A[offset + i];
            for (int j = i + 1; j < length; j++) {
                product = multi(product, A[offset + j]);
                if (product < 0) break;
                sum += A[offset + j];
                if (sum == product)
                    ans++;
            }
        }
        return ans;
    }

    long multi(long arg0, long arg1) {
        long product = arg0 * arg1;
        return product / arg1 == arg0 ? product : -1;
    }

    class InputReader {

        BufferedReader reader;
        StringTokenizer token;

        InputReader(InputStream in) {
            this.reader = new BufferedReader(new InputStreamReader(in));
        }

        String read() {
            while (token == null || !token.hasMoreTokens()) {
                try {
                    token = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return token.nextToken();
        }

        int readInt() { return Integer.parseInt(read()); }
    }
}

??給這題錘的神志不清了,有無大哥指點一下迷津,


#H 巧克力

時間限制: 1.0 1.0 1.0s 記憶體限制: 512.0 512.0 512.0MB 本題總分: 20 20 20


問題描述

??小藍很喜歡吃巧克力,他每天都要吃一塊巧克力,
??一天小藍到超市想買一些巧克力,超市的貨架上有很多種巧克力,每種巧克力有自己的價格、數量和剩余的保質期天數,小藍只吃沒過保質期的巧克力,請問小藍最少花多少錢能買到讓自己吃 x x x 天的巧克力,


輸入格式

??輸入的第一行包含兩個整數 x , n x, n x,n,分別表示需要吃巧克力的天數和巧克力的種類數,
??接下來 n n n 行描述貨架上的巧克力,其中第 i i i 行包含三個整數 a i , b i , c i a_{i}, b_{i}, c_{i} ai?,bi?,ci?,表示第 i i i 種巧克力的單價為 a i a_{i} ai?,保質期還剩 b i b_{i} bi? 天(從現在開始的 b i b_{i} bi? 天可以吃),數量為 c i c_{i} ci?


輸出格式

??輸出一個整數表示小藍的最小花費,如果不存在讓小藍吃 x x x 天的購買方案,輸出 ? 1 ?1 ?1


測驗樣例1

Input:
10 3
1 6 5
2 7 3
3 10 10

Output:
18

Explanation:
一種最佳的方案是第 1 種買 5 塊,第 2 種買 2 塊,第 3 種買 3 塊,前 5 天吃第 1 種,第 6、7 天吃第 2 種,第 8 至 10 天吃第 3 種,

評測用例規模與約定

??對于 30 30 30% 的評測用例, n , x ≤ 1000 n, x \leq 1000 n,x1000
??對于所有評測用例, 1 ≤ n , x ≤ 100000 1 \leq n, x \leq 100000 1n,x100000 1 ≤ a i , b i , c i ≤ 1 0 9 1 \leq a_{i}, b_{i}, c_{i} \leq 10^{9} 1ai?,bi?,ci?109


貪心演算法


??優先考慮最便宜的巧克力,每種巧克力盡可能晚的吃,直至已經吃了 x x x 天或再無可選擇的巧克力,

??簡單證明一下就是,如果存在比當前方案所有巧克力都便宜的巧克力,插入到任意可行的位置都會使當前方案的花費減小,因此按價格升序考慮巧克力的安排,

??然后就是當前在一個日期選擇的巧克力要盡可能的不影響到后面巧克力的選擇,而在一個當前最便宜的巧克力的保質期的區間,只會出現當前巧克力可選,后繼巧克力也可選和當前巧克力可選,后繼巧克力不可選兩種情況,顯然在都可選情況里選當前巧克力最優,而在后繼不可選情況里,越靠近保質期結束對后繼巧克力的選擇影響最小,

??狗屁不通真就那個論證失敗但合理能讓代碼跑過樣例,


import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) { new Main().run(); }

    void run() {
        InputReader in = new InputReader(System.in);
        int x = in.readInt(), n = in.readInt();
        boolean[] calender = new boolean[x + 1];
        int[][] chocos = new int[n][3];
        long ans = 0, marked = 0;
        for (int i = 0; i < n; i++) {
            chocos[i][0] = in.readInt();
            chocos[i][1] =
                min(x, in.readInt());
            chocos[i][2] = in.readInt();
        }
        Arrays.sort(chocos,
            (a1, a2)->(a1[0] - a2[0]));
        for (int[] choco : chocos)
            while (choco[1] > 0 && choco[2] > 0) {
                if (!calender[choco[1]]) {
                    calender[choco[1]] = true;
                    ans += choco[0];
                    choco[2]--;
                    marked++;
                }
                choco[1]--;
            }
        System.out.println(marked == x ? ans : -1);
    }

    int min(int a, int b) { return a < b ? a : b; }

    class InputReader {

        BufferedReader reader;
        StringTokenizer token;

        InputReader(InputStream in) {
            this.reader = new BufferedReader(new InputStreamReader(in));
        }

        String read() {
            while (token == null || !token.hasMoreTokens()) {
                try {
                    token = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return token.nextToken();
        }

        int readInt() { return Integer.parseInt(read()); }
    }
}

??可是樸素貪心的去求解這個問題,以這個解法為例,時間復雜度在 O ( n log ? n + n max ? ( b i , x ) ) O(n \log n + n \max (b_{i}, x)) O(nlogn+nmax(bi?,x)),接近 O ( n 2 ) O(n^2) O(n2) 顯然在這個資料規律下,還是相當不理想的,

??不過這種動態更新標記,查找最小可用,這和一個常用資料結構很契合,


并查集優化


??在確定完貪心策略后,程式中很大的一個性能瓶頸,出現在查找保質期內最大未規劃巧克力的時間,

??如果我們將一串規劃好的時間按原順序組成鏈表,那么在鏈頭大于一的情況下,鏈頭左邊的元素,就是我們要找的值,

??并且不需要關心這樣組織起的鏈表其他資訊,我們只需上述的資訊就能優化整個查找操作,并查集就能完成這項任務,

??并且在路徑壓縮的基礎上,這個操作的時間復雜程度只有 O ( 1 ) O(1) O(1)


import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) { new Main().run(); }

    int[] link;

    void run() {
        InputReader in = new InputReader(System.in);
        int x = in.readInt(), n = in.readInt();
        int[][] chocos = new int[n][3];
        long ans = 0, marked = 0;
        link = new int[x + 1];
        for (int i = 0; i < n; i++) {
            chocos[i][0] = in.readInt();
            chocos[i][1] =
                min(x, in.readInt());
            chocos[i][2] = in.readInt();
        }
        Arrays.fill(link, -1);
        Arrays.sort(chocos,
            (a1, a2)->(a1[0] - a2[0]));
        for (int[] choco : chocos)
            while (choco[2]-- > 0) {
                int d = find(choco[1]);
                if (d > 0) {
                    link[d] = d - 1;
                    ans += choco[0];
                    marked++;
                } else break;
            }
        System.out.println(marked == x ? ans : -1);
    }

    int find(int x) { return link[x] == -1 ? x : (link[x] = find(link[x])); }

    int min(int a, int b) { return a < b ? a : b; }

    class InputReader {

        BufferedReader reader;
        StringTokenizer token;

        InputReader(InputStream in) {
            this.reader = new BufferedReader(new InputStreamReader(in));
        }

        String read() {
            while (token == null || !token.hasMoreTokens()) {
                try {
                    token = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return token.nextToken();
        }

        int readInt() { return Integer.parseInt(read()); }
    }
}

??時間復雜度為 O ( n log ? n + n + x ) O(n \log n + n + x) O(nlogn+n+x),即 O ( n log ? n ) O(n \log n) O(nlogn)

??當然這里影響運行速度的引數不止 n n n 一個,

??能力有限,這里不做過多的討論,


貪心 + 大根堆


??為了能部分屏蔽除 n n n 以外的變數對程式整體運行時間的影響,我們需要按種而不是按塊來討論巧克力的規劃,

??但在上述貪心策略程序中,待規劃的日期是不連續的,如果將可安排日期按段查找,付出的代價可能遠比之前要大,額外增加的代碼量相應的也會增加除錯的風險與成本,

??容易地再想到一個策略,對于每個日期 d d d,在不選擇變質巧克力的前提下,盡可能的選擇最便宜的 d d d 個巧克力,

??對此我們可以按保質期升序考慮每種巧克力,動態的維護選擇方案,

?更詳細的說:

??建立一個以價格為權值的大根堆,該堆代表已選中的巧克力,堆初始為空,

?按保質期升序列舉巧克力的種類,列舉時會遇見兩種情況:

?1、當前巧克力數量 + 當前已選巧克力數量 ≤ \leq 當前巧克力保質期

??這時我們視為選擇當前巧克力,直接將其插入到堆里,

?2、當前巧克力數量 + 當前已選巧克力數量 > > > 當前巧克力保質期

??我們先計算出兩項的不等式兩邊的絕對差,然后從堆中彈出價格大于當前巧克力的巧克力,并且數量不能大于這個差值,然后插入若干當前種類的巧克力,使得當前已選巧克力數量等于當前巧克力保質期,

??可以預見的是,最終如果第 d d d 便宜的巧克力沒有加入第 d d d 天的方案,這就意味著在第 d d d 便宜的巧克力保質期內,有更便宜的巧克力使得第 d d d 便宜的巧克力無法加入,所以這個貪心策略下的結果是最優的,

??最終,堆內的巧克力就是最優的選擇方案,

??當然,它可能排不滿 x x x 天,


\\ 不想寫

#I 翻轉括號序列

時間限制: 10.0 10.0 10.0s 記憶體限制: 768.0 768.0 768.0MB 本題總分: 25 25 25


問題描述

??給定一個長度為 n n n 的括號序列,要求支持兩種操作:
?? 1 1 1. 將 [ L i , R i ] [L_{i}, R_{i}] [Li?,Ri?] 區間內(序列中的第 L i L_{i} Li? 個字符到第 R i R_{i} Ri? 個字符)的括號全部翻轉(左括號變成右括號,右括號變成左括號),
?? 2 2 2. 求出以 Li 為左端點時,最長的合法括號序列對應的 R i R_{i} Ri? (即找出最大的 R i R_{i} Ri? 使 [ L i , R i ] [L_{i}, R_{i}] [Li?,Ri?] 是一個合法括號序列),


輸入格式

??輸入的第一行包含兩個整數 n , m n, m n,m,分別表示括號序列長度和操作次數,
??第二行包含給定的括號序列,括號序列中只包含左括號和右括號,
??接下來 m m m 行,每行描述一個操作,如果該行為 “ 1 L i R i ” “1 L_{i} R_{i}” 1Li?Ri?,表示第一種操作,區間為 [ L i , R i ] [L_{i}, R_{i}] [Li?,Ri?];如果該行為 “ 2 L i ” “2 L_{i}” 2Li? 表示第二種操作,左端點為 L i L_{i} Li?


輸出格式

??對于每個第二種操作,輸出一行,表示對應的 R i R_{i} Ri?,如果不存在這樣的 R i R_{i} Ri?,請輸出 0 0 0


測驗樣例1

Input:
7 5
((())()
2 3
2 2
1 3 5
2 3
2 1

Output:
4
7
0
0

評測用例規模與約定

??對于 20 20 20% 的評測用例, n , m ≤ 5000 n, m \leq 5000 n,m5000
??對于 40 40 40% 的評測用例, n , m ≤ 30000 n, m \leq 30000 n,m30000
??對于 60 60 60% 的評測用例, n , m ≤ 100000 n, m \leq 100000 n,m100000
??對于所有評測用例, 1 ≤ n ≤ 1 0 6 , 1 ≤ m ≤ 2 × 1 0 5 1 \leq n \leq 10^{6}, 1 \leq m \leq 2 × 10^{5} 1n106,1m2×105


線段樹


??對于一個合法的括號序列,

??它總是以 ‘(’ 開始,使用堆疊來判斷一個序列是否為合法的單調序列,即堆疊內只存放 ‘(’ ,遍歷序列時遇到 ‘(’ 壓入堆疊里,遇到 ‘)’ 若堆疊為空則序列非法,否則彈出堆疊頂 ‘(’,若遍歷完成堆疊為空,則序列合法,否則序列非法,

??很容易發現 ‘(’ 對堆疊大小的貢獻為 ‘ 1 1 1’,而 ‘)’ 對堆疊大小的貢獻為 ‘ ? 1 -1 ?1’,一個合法的括號序列始終不會為堆疊空時遇到 ‘)’ ,

??我們可以用括號序列構建 ± 1 \pm1 ±1 序列,并計算出它的前綴和陣列 s u m sum sum

??按照上述性質,一個括號序列合法的充分條件是 s u m [ L ? 1 ] = s u m [ R ] 且 ? m ∈ [ L , R ] 都 有 s u m [ m ] ≥ s u m [ L ? 1 ] sum[L - 1] = sum[R]\ 且\ \forall m \in[L,R]都有sum[m] \ge sum[L - 1] sum[L?1]=sum[R] ?m[L,R]sum[m]sum[L?1]??再證其必要性,

??若有上述條件,則區間 s u m [ L , R ] sum[L,R] sum[L,R] 存在峰值 s u m [ k ] sum[k] sum[k],而原括號序列 k k k 位必然為 ‘(’ ,因為 k k k 為峰值,所以 s u m [ k + 1 ] = s u m [ k ] ? 1 sum[k + 1] = sum[k] - 1 sum[k+1]=sum[k]?1,即原括號序列 k + 1 k + 1 k+1 位必然為 ‘)’ , [ k , k + 1 ] [k,k+1] [k,k+1] 為一個合法的括號序列,將其從序列中剔除,如存在多個峰值則同時剔除多個,重復此程序直至序列為空,

??證畢,

??現在將問題轉變為查找區間最小值,如果我們動態維護一個線段樹的話,同時我們也能使用懶節點優化區間的翻轉,

\\節點懶,我也懶

#J 異或三角

時間限制: 5.0 5.0 5.0s 記憶體限制: 512.0 512.0 512.0MB 本題總分: 25 25 25


問題描述

??給定 T T T 個數 n 1 , n 2 , ? ? ? , n T n_{1}, n_{2}, · · · , n_{T} n1?,n2?,???,nT?,對每個 n i n_{i} ni? 請求出有多少組 a , b , c a, b, c a,b,c 滿足:
?? 1 1 1. 1 ≤ a , b , c ≤ n i 1 \leq a, b, c \leq n_{i} 1a,b,cni?
?? 2 2 2. a ⊕ b ⊕ c = 0 a \oplus b \oplus c = 0 abc=0,其中 ⊕ \oplus 表示二進制按位異或;
?? 3 3 3. 長度為 a , b , c a, b, c a,b,c 的三條邊能組成一個三角形,


輸入格式

??輸入的第一行包含一個整數 T T T
??接下來 T T T 行每行一個整數,分別表示 n 1 , n 2 , ? ? ? , n T n_{1}, n_{2}, · · · , n_{T} n1?,n2?,???,nT?


輸出格式

??輸出 T T T 行,每行包含一個整數,表示對應的答案,


測驗樣例1

Input:
2
6
114514

Output:
6
11223848130

評測用例規模與約定

??對于 10 10 10% 的評測用例, T = 1 , 1 ≤ n i ≤ 200 T = 1, 1 \leq n_{i} \leq 200 T=1,1ni?200
??對于 20 20 20% 的評測用例, T = 1 , 1 ≤ n i ≤ 2000 T = 1, 1 \leq n_{i} \leq 2000 T=1,1ni?2000
??對于 50 50 50% 的評測用例, T = 1 , 1 ≤ n i ≤ 2 20 T = 1, 1 \leq n_{i} \leq 2^{20} T=1,1ni?220
??對于 60 60 60% 的評測用例, 1 ≤ T ≤ 100000 , 1 ≤ n i ≤ 2 20 1 \leq T \leq 100000, 1 \leq n_{i} \leq 2^{20} 1T100000,1ni?220
??對于所有評測用例, 1 ≤ T ≤ 100000 , 1 ≤ n i ≤ 2 30 1 \leq T ≤ 100000, 1 \leq n_{i} \leq 2^{30} 1T100000,1ni?230


???這資料


線性遞推


??都線性了,那 40 40 40% 的 2 30 2^{30} 230 就不用想了,

??先是要確定幾個能幫助我們加快程式運行速度的性質,

?? a ⊕ a = 0 a \oplus a = 0 aa=0 0 ⊕ 0 = 0 0 \oplus 0 = 0 00=0,因此 a , b , c a,b,c a,b,c 互不相等,對于最終計算出的方案數,我們只需在計算時滿足 a > b > c a > b > c a>b>c,然后對結果乘以 3 ! 3! 3!

??而 a < b + c a < b + c a<b+c 才能組成三角形,故需要滿足 a = b ⊕ c < b + c a = b \oplus c < b + c a=bc<b+c

??我們都知道異或還有個別名,模二意義下的加法,也就是兩個數做異或運算相當在二進制下做加法并舍棄進位,

??因此當 b b b c c c 有任意一位同為 1 1 1 時,加法運算發生進位,不等式成立,

??再考慮對任意 a a a 可能的方案數,

?? a ≥ 1 a \ge 1 a1,因此 a a a 能被表示為 1 x 1 x 2 ? x m 1x_{1}x_{2}\cdots x_{m} 1x1?x2??xm? 這種 1 1 1 接后繼二進制串的形式;為了使 a > b > c a > b > c a>b>c b b b c c c 的二進制表示長度不會大于 a a a;為了使 a = b ⊕ c a = b \oplus c a=bc b b b 也必須被表現為 1 y 1 y 2 ? y m 1y_{1}y_{2}\cdots y_{m} 1y1?y2??ym? 這種形式;

??因此 b b b 絕對大于 c c c,所以我們可以直接跳過對 c c c 的討論,

??受上述條件限制, c c c 有和 b b b 相同位 1 1 1 的充分條件是 a a a 在此位為 0 0 0,所以 b b b 在小于 a a a 的同時,必須還有一位二進制數與 a a a 相反,為了滿足這個性質,這里換一種思路,

??直接選擇所有 1 y 1 y 2 ? y m 1y_{1}y_{2}\cdots y_{m} 1y1?y2??ym? y 1 y 2 ? y m < x 1 x 2 ? x m y_{1}y_{2}\cdots y_{m} < x_{1}x_{2}\cdots x_{m} y1?y2??ym?<x1?x2??xm?,然后從中剔除不滿足性質的元素,

??選擇這個集合等價于增加 a a a 去掉前導 1 1 1 的一串二進制數,而去掉不滿足性質的元素,等價于減去 2 2 2 的這串二進制數中 1 1 1 的個數次冪,

??舉個例子:

??設 a a a 0 b 101011 0\mathrm{b}101011 0b101011 b b b 必大于 0 b 100000 0\mathrm{b}100000 0b100000,因此我們直接選中 [ 0 b 100000 , 0 b 101011 ) [0\mathrm{b}100000,0\mathrm{b}101011) [0b100000,0b101011) 0 b 101011 ? 0 b 100000 = 0 b 1011 0\mathrm{b}101011 - 0\mathrm{b}100000 = 0\mathrm{b}1011 0b101011?0b100000=0b1011 個元素,而不存在 a a a 該位為 0 0 0 b b b 不為 1 1 1 這種情況的集合為 { 0 b x 1 0 x 2 x 3 } \{0\mathrm{b}x_{1}0x_{2}x_{3}\} {0bx1?0x2?x3?} x i ∈ 0 o r 1 x_{i} \in 0\ or\ 1 xi?0 or 1,顯然集合元素數量為 2 c o u n t B i t ( 0 b 1011 ) 2^{\mathrm{countBit}(0\mathrm{b}1011)} 2countBit(0b1011),相減后即為我們想要的結果,


import java.io.*;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) { new Main().run(); }

    void run() {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        int T = in.readInt(), upper = 0;
        int[] Q = new int[T];
        for (int i = 0; i < T; i++)
            upper = max(upper, Q[i] = in.readInt());
        long[] A = new long[upper + 1];
        for (int i = 1; i <= upper; i++) {
            int b = i - highBit(i);
            A[i] = A[i - 1] + b - (1 << countBit(b)) + 1;
        }
        for (int i = 0; i < T; i++)
            out.println(6 * A[Q[i]]);
        out.flush();
    }

    int highBit(int n) {
        n |= (n >> 1);
        n |= (n >> 2);
        n |= (n >> 4);
        n |= (n >> 8);
        n |= (n >> 16);
        return n - (n >>> 1);
    }

    int countBit(int n) {
        n = n - ((n >>> 1) & 0x55555555);
        n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);
        n = (n + (n >>> 4)) & 0x0f0f0f0f;
        n += n >>> 8;
        n += n >>> 16;
        return n & 0x3f;
    }

    int max(int a, int b) { return a > b ? a : b; }

    class InputReader {

        BufferedReader reader;
        StringTokenizer token;

        InputReader(InputStream in) {
            this.reader = new BufferedReader(new InputStreamReader(in));
        }

        String read() {
            while (token == null || !token.hasMoreTokens()) {
                try {
                    token = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return token.nextToken();
        }

        int readInt() { return Integer.parseInt(read()); }
    }
}

數位DP


// 不會,在學

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/327983.html

標籤:java

上一篇:我是如何用單例模式征服面試官的?

下一篇:Java基礎總結

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more