2023第十四屆藍橋杯大賽軟件賽國賽C/C++ 大學 B 組(真題題解)(C++/Java題解)

本來想刷省賽題呢,結果一不小心刷成國賽了
真是個小迷糊〒▽〒
但,又如何( ?? ω ?? )?
記錄刷題的過程、感悟、題解。
希望能幫到,那些與我一同前行的,來自遠方的朋友😉


大綱:

一、子2023-(題解)-遞推or動態規劃

二、雙子數-(題解)-篩法、類型(unsigned long long)😥

三、班級活動-(題解)-不出所料、貪心+計數

四、合并數列-(題解)-妥妥的前綴和😥,當然雙指針也能做

五、數三角-(題解)-這個真的就是算術題了,還要用到各種優化(叉乘、用半徑分組)

六、刪邊問題-(題解)-圖(tarjan算法)割邊、割點,經典板子題

七、AB路線-(題解)-BFS廣搜,最短路徑、記憶話搜索😉

八、抓娃娃-(題解)-簡單點的差分+前綴和😊

九、十,等后續沖擊國賽時,再解決。


一、子2023

問題描述

小藍在黑板上連續寫下從?11?到?20232023?之間所有的整數,得到了一個數字序列:?S=12345678910111213...20222023S=12345678910111213...20222023。 小藍想知道?SS?中有多少種子序列恰好等于?20232023?

以下是?33?種滿足條件的子序列(用中括號標識出的數字是子序列包含的數字):

1[2]34567891[0]111[2]1[3]14151617181920212223...
1[2]34567891[0]111[2]1[3]14151617181920212223...
1[2]34567891[0]111[2]131415161718192021222[3]...
1[2]34567891[0]111[2]131415161718192021222[3]...
1[2]34567891[0]111213141516171819[2]021222[3]...
1[2]34567891[0]111213141516171819[2]021222[3]...

注意以下是不滿足條件的子序列,雖然包含了?22、00、22、33?四個數字,但是順序不對:

1[2]345678910111[2]131415161718192[0]21222[3]...
1[2]345678910111[2]131415161718192[0]21222[3]...

答案提交

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

動態規劃解法:

本題解法,說成是狀態規劃,可能會引起恐懼,其實它就是一道簡單的狀態推導題( ?? ω ?? )?

C++
#include <iostream>
#include <vector>
using namespace std;
// 是個簡單的動態規劃就算了
// 怎么又是一道越界題目
// 以后統一不用long long改用 unsigned long long。更大。
int main(){vector<unsigned long long> dp(4,0);string str="";for(int i=1; i<=2023; ++i) str+=to_string(i);// 本題的解法是動態規劃for(char c : str){if(c=='2'){dp[0]++;dp[2]+=dp[1];}if(c=='0') dp[1]+=dp[0];if(c=='3') dp[3]+=dp[2];}cout<<dp[3]<<endl;return 0;
}
Java
public class DpProblem {public static void main(String[] args) {// 創建一個長度為 4 的 long 類型數組 dp 并初始化為 0long[] dp = new long[4];// 拼接字符串StringBuilder str = new StringBuilder();for (int i = 1; i <= 2023; i++) {str.append(i);}// 動態規劃過程for (int i = 0; i < str.length(); i++) {char c = str.charAt(i);if (c == '2') {dp[0]++;dp[2] += dp[1];}if (c == '0') {dp[1] += dp[0];}if (c == '3') {dp[3] += dp[2];}}// 輸出結果System.out.println(dp[3]);}
}    

二、雙子數

問題描述

若一個正整數?xx?可以被表示為?p2×q2p2×q2,其中?pp、qq?為質數且?p≠qp=q,則?xx?是一個雙子數。請計算區間?[2333,?23333333333333?][2333,?23333333333333?]?內有多少個雙子數

答案提交

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

// 我本以為,本題最難的是歐拉篩,也就是線性篩
// 后來我發現,我錯了,而且錯的離譜
// 歐拉篩,能用埃氏篩代替,能用樸素也就是暴力法代替。
// 而本題最大的難點是符號位,如果你開到(long long),答案會始終多10,讓你痛不欲生。
// 本題要開到,unsigned long long
// int->1e9 , long long->1e18, unsigned long long是longlong的兩倍

// 切記,不會歐拉篩的,可以用線性篩代替,或者直接暴力(會慢一些):: 四種篩法 ::

C++
#include <iostream>
#include <vector>
#define ll long long
using namespace std;const int N =  1e7 + 10;
vector<bool> vec(N, true); // 假設都是質數
vector<ll> res;
void sieve(){ // 歐拉篩vec[0]=vec[1]= false;for(int i=2; i<vec.size(); ++i){if(vec[i]) res.push_back((ll)i);for(ll num:res){if(num*i>vec.size()) break; // 超出最大范圍vec[i*num] = false;if(i%num==0) break; // 確保每個合數,只被最小因子除去。}}
}
//天吶,你要這樣玩?還咋玩??
int main(){sieve();ll num = 0;for(ll i=0;i<res.size();i++){unsigned ll pp = res[i]*res[i];if(pp * pp >23333333333333) break;//一點小優化for(ll j=i+1;j<res.size();j++){ll qq = res[j]*res[j];if(pp*qq>23333333333333) break;if(pp*qq<2333) continue;num++;}}cout<<num<<endl;return 0;
}
Java
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;public class PrimeNumberCombination {// 定義常量 N,用于篩法范圍static final int N = 10000010;// 標記每個數是否為質數的布爾數組static boolean[] isPrime = new boolean[N];// 存儲質數的列表static List<Integer> primes = new ArrayList<>();// 歐拉篩函數,篩選出所有質數public static void sieve() {// 初始化所有數為質數for (int i = 0; i < N; i++) {isPrime[i] = true;}// 0 和 1 不是質數isPrime[0] = isPrime[1] = false;for (int i = 2; i < N; i++) {if (isPrime[i]) {primes.add(i);}for (int prime : primes) {if (prime * i >= N) {break;}isPrime[prime * i] = false;if (i % prime == 0) {break;}}}}public static void main(String[] args) {// 調用歐拉篩函數sieve();BigInteger limit1 = BigInteger.valueOf(23333333333333L);BigInteger limit2 = BigInteger.valueOf(2333L);long num = 0;for (int i = 0; i < primes.size(); i++) {BigInteger pp = BigInteger.valueOf(primes.get(i)).pow(2);if (pp.pow(2).compareTo(limit1) > 0) {break;}for (int j = i + 1; j < primes.size(); j++) {BigInteger qq = BigInteger.valueOf(primes.get(j)).pow(2);BigInteger product = pp.multiply(qq);if (product.compareTo(limit1) > 0) {break;}if (product.compareTo(limit2) < 0) {continue;}num++;}}// 輸出滿足條件的組合數量System.out.println(num);}
}    

三、班級活動

問題描述

小明的老師準備組織一次班級活動。班上一共有?nn?名 (nn?為偶數) 同學,老師想把所有的同學進行分組,每兩名同學一組。為了公平,老師給每名同學隨機分配了一個?nn?以內的正整數作為?idid,第?ii?名同學的?idid?為?aiai?。

老師希望通過更改若干名同學的?idid?使得對于任意一名同學?ii,有且僅有另一名同學?jj?的?idid?與其相同 (ai=ajai?=aj?)。請問老師最少需要更改多少名同學的?idid?

輸入格式

輸入共?22?行。

第一行為一個正整數?nn。

第二行為?nn?個由空格隔開的整數?a1,a2,...,ana1?,a2?,...,an?。

輸出格式

輸出共?11?行,一個整數。

樣例輸入

4
1 2 2 3

樣例輸出

1

樣例說明

僅需要把?a1a1??改為?33?或者把?a3a3??改為?11?即可。

評測用例規模與約定

對于?20%20%?的數據,保證?n≤103n≤103。

對于?100%100%?的數據,保證?n≤105n≤105

// ?_??當我找到哪里錯了之后,淚流滿面
// 本題其實挺簡單
// 讀題:“每名同學,隨機分配n以內的正整數作為id”?
// 這說明,每個同學的id有兩種情況。
// 此時舉一個簡單的例子就OK了
// 像題目中舉得例子,1 2 2 3 一組(2,2)就能配對,僅需更改3變成1(1->3也行)就OK了,只需一次。
// 推算成公式,也就是 2/1=1 -> 散列的總數/2
// 進階一點,當id為 2 2 2 1時,此時一組(2,2)就能配對,這時僅需更改剩下的2變成1就OK了,也只需要更改一次。
// 如果是 2 2 2 2 2 1 呢,要先去掉一組(2,2)
// 此時剩下 2 2 2 1,因為不能與已經配對的(2,2)重復,
// 所以先把其中一個2改為1,需要一次。
// 此時剩下 2 2,只需將它們改成其他數就行,如改成(3,3),需要兩次。
// 一共用了3次,也就是2的總數 減去2 也就是減去(2,2)這個不需要改變的組合。
// 也就是 當已被占用的id的數量,大于未被占用id時,總數等于 重復 id的數量。

C++
#include <iostream>
const int N = 1e5+5;
using namespace std;
int arr[N]; int main()
{int n;cin>>n;for(int i=0; i<n; ++i){int num;cin>>num;arr[num]++;}int num1=0, num2=0;for(int i : arr){if(i>2) num1 += i-2; // 求取數量相同的數在減2;else if(i==1) num2++;}int sum = 0;// 當已被占用的id的數量,大于未被占用id時,那么sum = num1;if(num1>num2){sum = num1;  }else{ // num2<num1的情況sum = num2 + (num1-num2)/2;}cout<<sum<<endl;return 0;
}
Java
import java.util.Scanner;public class StudentIdAdjustment {// 定義常量 N,用于數組大小static final int N = 100005;public static void main(String[] args) {// 創建 Scanner 對象用于讀取輸入Scanner scanner = new Scanner(System.in);// 定義一個數組來記錄每個 ID 出現的次數int[] arr = new int[N];// 讀取學生的數量int n = scanner.nextInt();// 循環讀取每個學生的 ID,并統計每個 ID 出現的次數for (int i = 0; i < n; i++) {int num = scanner.nextInt();arr[num]++;}// 初始化兩個變量,用于統計需要處理的不同情況的數量int num1 = 0;int num2 = 0;// 遍歷數組,統計 num1 和 num2 的值for (int i : arr) {// 如果某個 ID 出現的次數大于 2,計算超出 2 的部分并累加到 num1if (i > 2) {num1 += i - 2;} // 如果某個 ID 只出現了 1 次,將 num2 加 1else if (i == 1) {num2++;}}// 初始化最終結果變量int sum = 0;// 當 num1 大于 num2 時,說明已被占用的 ID 數量更多,sum 等于 num1if (num1 > num2) {sum = num1;} // 當 num2 大于等于 num1 時,按照相應規則計算 sumelse {sum = num2 + (num1 - num2) / 2;}// 輸出最終結果System.out.println(sum);// 關閉 Scanner 對象,釋放資源scanner.close();}
}    

四、合并數列

問題描述

小明發現有很多方案可以把一個很大的正整數拆成若干正整數的和。他采取了其中兩種方案,分別將他們列為兩個數組?{a1,a2,...,an}{a1?,a2?,...,an?}?和?{b1,b2,...,bm}{b1?,b2?,...,bm?}。兩個數組的和相同。

定義一次合并操作可以將某數組內相鄰的兩個數合并為一個新數,新數的值是原來兩個數的和。小明想通過若干次合并操作將兩個數組變成一模一樣,即?n=mn=m?且對于任意下標?ii?滿足?ai=biai?=bi?。請計算至少需要多少次合并操作可以完成小明的目標。

輸入格式

輸入共?33?行。

第一行為兩個正整數?nn,?mm。

第二行為?nn?個由空格隔開的整數?a1,a2,...,ana1?,a2?,...,an?。

第三行為?mm?個由空格隔開的整數?b1,b2,...,bmb1?,b2?,...,bm?。

輸出格式

輸出共?11?行,一個整數。

樣例輸入

4 3
1 2 3 4
1 5 4

樣例輸出

1

樣例說明

只需要將?a2a2??和?a3a3??合并,數組?aa?變為?{1,5,4}{1,5,4},即和?bb?相同。

評測用例規模與約定

對于?20%20%?的數據,保證?nn,?m≤103m≤103。

對于?100%100%?的數據,保證?nn,?m≤105m≤105,0<ai0<ai?,?bi≤105bi?≤105。

// 本題原意:“兩個數列,通過不斷合并相鄰的兩個數,使兩個數列相同”
// 注意-“相鄰” “合并(相加)”,也就意味著可能要使用前綴和。
// 用反向思維來看,兩個數列最終是相同的。
// 也就意味著從倆數列,第一個數開始,就要是相同的。
// 我們只需要從頭開始計算前綴和,如果相同時,代表倆數列第i位已經相同,
// 此時更新倆前綴和的計算起始位置即可。
// 所以本題是,雙指針與前綴和的結合。

1 2 3 4
1 5 4
------------
對比兩個數列的第一位,相同,不用變
------------
3 3 4
6 4
第一位不同,合并小的前兩位
----------
6 4
6 4
....

// 本題又讓我痛哭不已,類型開小了,本題最大有1e10左右,int不太行

C++
#include <iostream>
#include <vector>
using namespace std;int main()
{int n,m;cin>>n>>m;vector<int> a(n,0);vector<int> b(m,0);for(int i=0; i<n; ++i) cin>>a[i];for(int i=0; i<m; ++i) cin>>b[i];// sum_a a數列的前綴和// sum_b b數列的前綴和// cnt_a a的位數// cnt_b b的位數// cnt_sum 總共需要的次數long long sum_a=0,sum_b=0,cnt_a=0,cnt_b=0,cnt_sum=0;while(true){if(sum_a==sum_b){sum_a+=a[cnt_a++];sum_b+=b[cnt_b++];}else if(sum_a<sum_b){ // 第一個值小,需要合并sum_a+=a[cnt_a++];cnt_sum++;}else if(sum_b<sum_a){ // 第二個值小,需要合并sum_b+=b[cnt_b++];cnt_sum++;}if(cnt_a==n&&cnt_b==m) break;}cout<<cnt_sum;return 0;
}
Java
import java.util.Scanner;public class MergeArrays {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 讀取兩個數組的長度int n = scanner.nextInt();int m = scanner.nextInt();// 初始化兩個數組int[] a = new int[n];int[] b = new int[m];// 讀取第一個數組的元素for (int i = 0; i < n; i++) {a[i] = scanner.nextInt();}// 讀取第二個數組的元素for (int i = 0; i < m; i++) {b[i] = scanner.nextInt();}// 初始化前綴和變量和指針long sum_a = 0, sum_b = 0; // 使用long避免大數溢出int cnt_a = 0, cnt_b = 0; // 數組a和b的當前指針位置int cnt_sum = 0; // 記錄合并次數// 循環處理直到兩個數組都遍歷完畢while (true) {// 當兩個前綴和相等時,移動到下一個元素if (sum_a == sum_b) {// 注意邊界條件:避免數組越界if (cnt_a < n) {sum_a += a[cnt_a++]; // 移動a的指針并累加值}if (cnt_b < m) {sum_b += b[cnt_b++]; // 移動b的指針并累加值}} else if (sum_a < sum_b) {// a的前綴和較小,需要合并下一個元素sum_a += a[cnt_a++]; // 合并a的下一個元素cnt_sum++; // 合并次數加1} else {// b的前綴和較小,需要合并下一個元素sum_b += b[cnt_b++]; // 合并b的下一個元素cnt_sum++; // 合并次數加1}// 檢查是否已經遍歷完兩個數組的所有元素if (cnt_a == n && cnt_b == m) {break;}}// 輸出最終的合并次數System.out.println(cnt_sum);scanner.close();}
}

五、數三角

問題描述

小明在二維坐標系中放置了?nn?個點,他想在其中選出一個包含三個點的子集,這三個點能組成三角形。然而這樣的方案太多了,他決定只選擇那些可以組成等腰三角形的方案。請幫他計算出一共有多少種選法可以組成等腰三角形?

輸入格式

輸入共?n+1n+1?行。

第一行為一個正整數?nn。

后面?nn?行,每行兩個整數?xixi?,?yiyi??表示第?ii?個點的坐標。

輸出格式

輸出共?11?行,一個整數。

樣例輸入

5
1 1
4 1
1 0
2 1
1 2

樣例輸出

4

樣例說明

一共有?44?種選法:?{3,4,5}{3,4,5}、{1,3,4}{1,3,4}、{5,2,3}{5,2,3}、{1,4,5}{1,4,5}。

評測用例規模與約定

對于?20%20%?的數據,保證?n≤200n≤200。

對于?100%100%?的數據,保證?n≤2000n≤2000,0≤xi,yi≤1090≤xi?,yi?≤109。

/*
? 本題要是直接3層暴力,肯定對,但是只能獲取60%的分!
? 所以要用上很多優化方式
? 如:根據半徑求解叉乘(在本文下方有講解,也可上網搜)判是否三點在一條直線上
? 通過vector<map<ll,vector<int>>> 預處理分組
? 最后用unordered_map存儲,O(1)

? 其實最開始,我也是有疑問的,這是怎么將O(n^3)優化到接近O(n^2)
? 畢竟預處理分組后下方仍有4層循環呢
? 其實畫個圖就好了。
? 沒優化之前,每個節點都要判斷(n^2)次,優化之后,每個節點僅需判斷分組過后的就行(哪怕是4層,其實有效的點不多,可近似成線性)。
*/

?C++
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;#define ll long long // 因為不可能出現負數,直接開到最大(unsigned long long)
const ll N = 2e3+5;struct point{int x;int y;
}p[N]; // 定義節點-預處理ll get_radius(int i, int j){ // 半徑的平方return (p[i].x-p[j].x)*(p[i].x-p[j].x) + (p[i].y-p[j].y)*(p[i].y-p[j].y);
}bool is_parallel(int i, int j, int k){ // 用叉乘的方法,快速判斷,這一步不會的,可以上網查詢叉乘的作用,以及用法。ll v = (p[j].x-p[i].x)*(p[k].y-p[i].y)-(p[j].y-p[i].y)*(p[k].x-p[i].x); // i-j(p[j].x-p[i].x),(p[j].y-p[i].y) 與 i-k(p[k].x-p[i].x),(p[k].y-p[i].y)if(v==0) return true;else return false;
}int main(){int n;cin>>n;for(int i=0; i<n; ++i) cin>>p[i].x>>p[i].y;vector<unordered_map<ll,vector<int>>> vec(n); // 存// 預處理,只需要耗時O(n^2),即可分堆,避免3層暴力的大量重復計算for(int i=0; i<n; ++i){unordered_map<ll,vector<int>> m; // 用半徑的平方儲存,這樣就不用開方了for(int j=0; j<n; ++j){if(i==j) continue;ll len = get_radius(i,j);m[len].push_back(j); // 把這個點存進去}vec[i] = m; // 把map存入}// 最大的優點就是避免了許多無意義的重復計算int sum = 0;for(int i=0; i<n; ++i){ // 找到這個點,判斷其內部的存儲auto m = vec[i]; // 這個的出來的知識map結合,里面幼嫩多for(auto it=m.begin(); it!=m.end(); ++it){vector<int> p_m = it->second;if(p_m.size()<=1) continue; // 這種情況下,跳過for(int j=0; j<p_m.size(); ++j){for(int k=j+1; k<p_m.size(); ++k){if(is_parallel(i,p_m[j],p_m[k])) continue; // 共線sum++;}}}}cout<<sum<<endl;return 0;
}
Java
import java.util.*;
public class Main {public static void main(String[] args) {//輸出部分//讀取輸入的點,并統計每個點的出現次數Scanner sc = new Scanner(System.in);int n = sc.nextInt();//輸入點的數量int[] x = new int [n + 10];//存儲每個點的x坐標int[] y = new int [n + 10];//存儲每個點的y坐標HashMap<String, Integer> s = new HashMap<>();//統計每個點的出現次數//鍵是點的坐標,如("1 2")for(int i = 0; i < n; i++){x[i] = sc.nextInt();//輸入第i個點的x坐標y[i] = sc.nextInt();//輸入第i個點的y坐標String t = x[i] + " " + y[i];//將坐標拼接成字符串作為鍵s.put(t, s.getOrDefault(t , 0) + 1);//統計讀點的出現次數}//計算核心部分//對于每個點i,計算它與其他所有點j的距離,并將距離相同的點分組long res = 0;//最終結果for(int i = 0; i < n; i++){HashMap< Long,List<Integer> > map = new HashMap<>();//存儲距離相同的點的索引for(int j = 0; j < n; j++){if(i == j) continue;//跳過自己long d = (long)(Math.pow(x[i] - x[j], 2) + Math.pow(y[i] - y[j] , 2));//計算距離的平方List<Integer> list = map.getOrDefault(d, new ArrayList<>());//初始化列表list.add(j);//將點j加入對應的列表map.put(d,list);//更新map}//map是一個哈希表,鍵是距離的平方(d)值是一個列表,存儲所有與點i距離為d的點的索引//d是點i和點j之間的距離的平方(為了節省計算量,沒有開平方)for(long b : map.keySet()){List<Integer>list = map.get(b);//獲取距離為b的所有點res += (list.size() * (list.size() - 1)) /2;//統計點的數量long c = 0;for(int j : list){long x3 = 2 * x[i] - x[j], y3 = 2 * y[i] - y[j];//計算對稱帶點x與y的坐標if(s.containsKey(x3 + " " + y3)){//拼接成字符串c += s.get(x3 + " " + y3);//統計對稱點的出現次數}}res -= c/2;//減去重復統計的點對}}System.out.println(res);}
}

六、刪邊問題

問題描述

給定一個包含?NN?個結點?MM?條邊的無向圖?GG,結點編號?1...N1...N。其中每個結點都有一個點權?WiWi?。

你可以從?MM?條邊中任選恰好一條邊刪除,如果剩下的圖恰好包含?22?個連通分量,就稱這是一種合法的刪除方案。

對于一種合法的刪除方案,我們假設?22?個連通分量包含的點的權值之和分別為?XX?和?YY,請你找出一種使得?XX?與?YY?的差值最小的方案。輸出?XX?與?YY?的差值。

輸入格式

第一行包含兩個整數?NN?和?MM。

第二行包含?NN?個整數,W1,W2,...WNW1?,W2?,...WN?。

以下?MM?行每行包含?22?個整數?UU?和?VV,代表結點?UU?和?VV?之間有一條邊。

輸出格式

一個整數代表最小的差值。如果不存在合法的刪除方案,輸出??1?1。

樣例輸入

4 4
10 20 30 40
1 2
2 1
2 3
3 4

樣例輸出

20

樣例說明

由于?11?和?22?之間實際有?22?條邊,所以合法的刪除方案有?22?種,分別是刪除?(2,3)(2,3)?之間的邊和刪除?(3,4)(3,4)?之間的邊。

刪除?(2,3)(2,3)?之間的邊,剩下的圖包含?22?個連通分量:?{1,2}{1,2}?和?{3,4}{3,4},點權和分別是?3030、7070,差為?4040。

刪除?(3,4)(3,4)?之間的邊,剩下的圖包含?22?個連通分量:?{1,2,3}{1,2,3}?和?{4}{4},點權和分別是?6060、4040,差為?2020。

評測用例規模與約定

對于?20%20%?的數據,1≤N,M≤100001≤N,M≤10000。

對于另外?20%20%?的數據,每個結點的度數不超過?22。

對于?100%100%?的數據,1≤N,M≤2000001≤N,M≤200000,0≤Wi≤1090≤Wi?≤109,1≤U,V≤N1≤U,V≤N。


// 本題為tarjan算法的變種,不懂的,可以先搜一下基本用法(涉及圖的知識),本文最底部,也有優質視頻的鏈接
/*
? 其實本題不難,只要有圖的基礎就行--(能看懂答案的前提)
? 連通分量:圖的一個子圖,這個子圖中,任意兩點之間,都存在可達路徑
? 然后就是 tarjan 算法(懂得可以不用看,建議先看視頻,知道tarjan是啥)
? *
? ? 用dfn(發現時間戳)與low(最低可達祖先的發現時間戳)。確切的說,他倆都是個編號。
? ? 然后用cnt(count)這個設置時間戳。每次++。
? ? --以上是tarjan算法模版--
? ? 建立一個函數tarjan(n,fa) // n是現節點,fa是父節點,避免重復用的
? ? 然后,遞歸調用每個現階段子節點(大致會先將所有)
? ? 此時有三種情況
? ? ? 1、是未被遍歷過的新節點
? ? ? ? (這時可以繼續向下搜索,等回退到這里時,
? ? ? ? (更新一下low值,若果現節點的dfn小于子節點的low值(dfn<low),代表連通兩節點的邊能被割去
? ? ? ? (為了計數,可以在維護一個w集合,用于儲存以本節點為結尾的總和
? ? ? 2、遍歷到了父節點
? ? ? ? (可以毫不猶豫的退回了)
? ? ? 3、遍歷到了非父節點的舊節點
? ? ? ? (這個可是更新low值的好時候
? ? ? ? (是為了給,回溯時,判斷是否能構成聯通圖 ? ?做準備
? *
? // 拓展-從割邊問題 -> 割點問題
? (割點問題時,需要將low小于等于dfn(low<=dfn)
? (為啥<=中,多了個等于?因為一旦刪掉這個點,整個鏈子就會斷開,Java解析下方有圖解
*/

C++
#include <iostream>
#include <cmath>
#include <vector>
#define ll long long
using namespace std;
const ll N = 1e6+5;
const ll maxn = 0x3f3f3f3f3f3f3f3f; // 定義“偽最大值”
ll n,m,sum_value=0,cnt=0,ans=maxn; // sum_value總和,cnt計數器vector<ll> dfn(N,0),low(N,0);
vector<int> vec[N]; // 定義鄰接表
vector<ll> value(N,0); // 每個節點的權值
vector<ll> node_sum(N,0); // 回退回來的節點總和void tarjan(int u, int fa){ // 現節點u、父節點fadfn[u]=low[u]=++cnt;for(int v:vec[u]){if(dfn[v]==0){   // 沒遍歷過tarjan(v,u);low[u] = min(low[v],low[u]);if(dfn[u]<low[v]) ans=min(ans,abs(sum_value-2*value[v]));value[u] += value[v];}else if(v!=fa){low[u]=min(low[u],low[v]);}}
}void slove(){ // 作為中轉站cin>>n>>m;for(int i=1; i<=n; ++i) cin>>value[i],sum_value+=value[i];for(int i=0; i<m; ++i){ // 將無向圖存入int r1,r2;cin>>r1>>r2;vec[r1].push_back(r2);vec[r2].push_back(r1);}// 現在啥都有了tarjan(1,0);if(value[1]!=sum_value) cout<<abs(sum_value-2*value[1])<<endl;else if(ans!=maxn) cout<<ans<<endl;else cout<<-1<<endl;
}int main(){slove();return 0;
}
Java
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;public class Main {// 定義常量 N 作為數組大小static final long N = (long) (1e6 + 5);// 定義“偽最大值”static final long maxn = 0x3f3f3f3f3f3f3f3fL;// 節點數量 n,邊的數量 mstatic long n, m;// 所有節點權值總和static long sum_value = 0;// 時間戳計數器static long cnt = 0;// 存儲最終結果static long ans = maxn;// 存儲每個節點的發現時間戳static List<Long> dfn = new ArrayList<>();// 存儲每個節點能回溯到的最早祖先的發現時間戳static List<Long> low = new ArrayList<>();// 鄰接表,存儲圖的結構static List<List<Integer>> vec = new ArrayList<>();// 存儲每個節點的權值static List<Long> value = new ArrayList<>();// Tarjan 算法核心函數static void tarjan(int u, int fa) {// 初始化當前節點的發現時間戳和最早祖先時間戳dfn.set(u, ++cnt);low.set(u, cnt);// 遍歷當前節點的所有鄰接節點for (int v : vec.get(u)) {if (dfn.get(v) == 0) { // 如果鄰接節點未被訪問過// 遞歸調用 Tarjan 算法處理鄰接節點tarjan(v, u);// 更新當前節點的最早祖先時間戳low.set(u, Math.min(low.get(u), low.get(v)));// 如果當前節點的發現時間戳小于鄰接節點的最早祖先時間戳,說明該邊是割邊if (dfn.get(u) < low.get(v)) {ans = Math.min(ans, Math.abs(sum_value - 2 * value.get(v)));}// 將鄰接節點的權值累加到當前節點value.set(u, value.get(u) + value.get(v));} else if (v != fa) { // 如果鄰接節點已被訪問且不是父節點// 更新當前節點的最早祖先時間戳low.set(u, Math.min(low.get(u), low.get(v)));}}}// 主處理函數static void solve() {Scanner scanner = new Scanner(System.in);// 讀取節點數量和邊的數量n = scanner.nextLong();m = scanner.nextLong();// 初始化列表for (int i = 0; i <= n; i++) {dfn.add(0L);low.add(0L);value.add(0L);vec.add(new ArrayList<>());}// 讀取每個節點的權值并計算總和for (int i = 1; i <= n; i++) {value.set(i, scanner.nextLong());sum_value += value.get(i);}// 讀取邊的信息并構建鄰接表for (int i = 0; i < m; i++) {int r1 = scanner.nextInt();int r2 = scanner.nextInt();vec.get(r1).add(r2);vec.get(r2).add(r1);}// 從節點 1 開始進行 Tarjan 算法tarjan(1, 0);// 如果節點 1 的權值總和不等于所有節點的權值總和if (value.get(1) != sum_value) {System.out.println(Math.abs(sum_value - 2 * value.get(1)));} else if (ans != maxn) { // 如果找到了割邊System.out.println(ans);} else { // 沒有找到符合條件的割邊System.out.println(-1);}}public static void main(String[] args) {// 調用主處理函數solve();}
}

?拓展(割點):

?

七、AB路線

問題描述

小明拿了?nn?條線段練習抓娃娃。他將所有線段鋪在數軸上,第?ii?條線段的左端點在?lili?,右端點在?riri?。小明用?mm?個區間去框這些線段,第?ii?個區間的范圍是 [LiLi?,?RiRi?]。如果一個線段有?至少一半?的長度被包含在某個區間內,則將其視為被這個區間框住。請計算出每個區間框住了多少個線段?

輸入格式

輸入共?n+m+1n+m+1?行。

第一行為兩個正整數?nn,?mm。

后面?nn?行,每行兩個整數?lili?,?riri?。

后面?mm?行,每行兩個整數?LiLi?,?RiRi?。

輸出格式

輸出共?mm?行,每行一個整數。

樣例輸入

3 2
1 2
1 3
3 4
1 4
2 4

樣例輸出

3
2

評測用例規模與約定

對于?20%20%?的數據,保證?n,m≤103n,m≤103。

對于?100%100%?的數據,保證?n,m≤105n,m≤105,li<rili?<ri?,0<li,ri,Li,Ri≤1060<li?,ri?,Li?,Ri?≤106,max?{ri?li}≤min?{Ri?Li}max{ri??li?}≤min{Ri??Li?}.

/*
? ?審題 “小藍最少要走多少步?”,“最少”
? ?BFS就是解決圖-最短路徑的特效藥,
? ?DFS深搜也能搜到,但不一定是最短的,深搜更傾向于排列組合、解數獨、八皇后,這種嘗試性的算法。
? ?好了,確定本題的基調,就是廣搜

? ?在開始之前,還需考慮一個問題,就是暴力搜索必然會超時,因此,枝減操作,必不可少。也就是要引入記憶化搜索。
? ?這個時候,就要思考,用什么存儲記憶化搜索
? ?注意本題 "格子數,要是K的倍數,所以這里涉及到了k"
? ?-used[i][j][k]; 其中k來儲存走到這個格式,連續走的步數。
? ?步數相同時,代表該地址已經被走過。相同的符號,相同的步數,所以可以直接跳過。
? ?(注意,這里不用三維數組標記,是會超時的)。

? ?所以本題用queue廣搜、used[i][j][k]記憶化搜索、res[i][j][k]標記走的這個位置,用了多少步。
*/

C++?
#include <iostream>
#include <queue>
using namespace std;const int N = 1e3+5;
const int step = 1e1+5;
struct node{int x;int y;int step;
};
int n,m,k;
queue<node> q; // 用隊列,實現廣搜
bool used[N][N][step]; // 預處理
int res[N][N][step]; // 表示,每個節點,都在那個狀態走過
char grid[N][N];int xf[]={1,-1,0,0}; // 用來記錄方向的改變
int yf[]={0,0,1,-1};int BFS(){q.push({0,0,0}); // 將第一個節點存入while(!q.empty()){node u = q.front(); q.pop(); // 取出該節點if(u.x==n-1 && u.y==m-1) return res[u.x][u.y][u.step];for(int i=0; i<4; ++i){int X = u.x+xf[i], Y = u.y+yf[i], st = u.step+1;if(X<0||X>=n||Y<0||Y>=m) continue; // 出邊界if(st<k&&grid[X][Y]!=grid[u.x][u.y]) continue;if(st==k&&grid[X][Y]==grid[u.x][u.y]) continue;st = st%k; // 時刻更新著if(used[X][Y][st]) continue; // 都是更新之后,在遍歷的used[X][Y][st]=true; // 表示遍歷過res[X][Y][st]=res[u.x][u.y][u.step]+1; // 多走了一步q.push({X,Y,st});}}return -1; // 此時還沒有解釋,只能說明一件事,遍歷到頭了,沒有結果。
}int main(){// 基本處理cin>>n>>m>>k;string str;for(int i=0; i<n; ++i){cin>>str;for(int j=0; j<m; ++j) grid[i][j]=str[j];}cout<<BFS();return 0;
}
Java
import java.math.BigInteger;
import java.util.*;public class Main {static long INF = (long) 1e18;public static void main(String[] args) {Scanner sc = new Scanner(System.in); int n = sc.nextInt();int m = sc.nextInt();int k = sc.nextInt();sc.nextLine();char[][] mg = new char[n][m];for (int i = 0; i < n; i++) {mg[i] = sc.nextLine().toCharArray();}LinkedList<Pair> qu = new LinkedList<Pair>();qu.add(new Pair(0, 0, 1));int[][] d = new int[][] {{0,1},{1,0},{0,-1},{-1,0}};boolean[][][] visited = new boolean[n][m][2 * k];for (int step = 0; !qu.isEmpty(); step++) {int num = qu.size();for (int i = 0; i < num; i++) {Pair pair = qu.pollFirst();int px = pair.x, py = pair.y, pf = pair.flag;if (visited[px][py][pf]) {continue;}visited[px][py][pf] = true;if (pair.x == n - 1 && pair.y == m - 1) {System.out.print(step);return;}for (int j = 0; j < 4; j++) {int x = px + d[j][0];int y = py + d[j][1];int f = (pf + 1) % (2 * k);if (x >= 0 && x < n && y >= 0 && y < m) {if (visited[x][y][f]) {continue;}if (pf < k && mg[x][y] == 'A' || pf >= k && mg[x][y] == 'B') {qu.addLast(new Pair(x, y, f));}}}}}System.out.print(-1);}
}class Pair {int x, y, flag;public Pair(int x, int y, int flag) {super();this.x = x;this.y = y;this.flag = flag;}
}

八、抓娃娃

問題描述

小明拿了?nn?條線段練習抓娃娃。他將所有線段鋪在數軸上,第?ii?條線段的左端點在?lili?,右端點在?riri?。小明用?mm?個區間去框這些線段,第?ii?個區間的范圍是 [LiLi?,?RiRi?]。如果一個線段有?至少一半?的長度被包含在某個區間內,則將其視為被這個區間框住。請計算出每個區間框住了多少個線段?

輸入格式

輸入共?n+m+1n+m+1?行。

第一行為兩個正整數?nn,?mm。

后面?nn?行,每行兩個整數?lili?,?riri?。

后面?mm?行,每行兩個整數?LiLi?,?RiRi?。

輸出格式

輸出共?mm?行,每行一個整數。

樣例輸入

3 2
1 2
1 3
3 4
1 4
2 4

樣例輸出

3
2

評測用例規模與約定

對于?20%20%?的數據,保證?n,m≤103n,m≤103。

對于?100%100%?的數據,保證?n,m≤105n,m≤105,li<rili?<ri?,0<li,ri,Li,Ri≤1060<li?,ri?,Li?,Ri?≤106,max?{ri?li}≤min?{Ri?Li}max{ri??li?}≤min{Ri??Li?}.

// 聰明的你,一定用的暴力,聰明的你,一定超時o(* ̄▽ ̄*)ブ?
// 本題,用差分+前綴和,就能非常完美的解決問題
// 此外,本題預處理化的時候,一定要看清楚!
// 不要處理成2e5+5了,要開r、l、R、L。而不是n,m;

C++
#include <iostream>
#include <vector>
const int N = 2e6+5;
using namespace std;int main()
{int n,m;cin>>n>>m;vector<int> res(N,0);for(int i=0,r,l; i<n; ++i) cin>>l>>r,res[r+l]++; for(int i=1; i<N; ++i) res[i]+=res[i-1];for(int i=1,L,R; i<=m; ++i){cin>>L>>R;L*=2,R*=2;if(L==0) cout<<res[R]<<endl;else cout<<res[R]-res[L-1]<<endl;}return 0;
}
Java
import java.util.Scanner;public class SegmentQuery {public static void main(String[] args) {// 定義常量 N,用于數組大小final int N = 2000005;Scanner scanner = new Scanner(System.in);// 讀取 n 和 m 的值int n = scanner.nextInt();int m = scanner.nextInt();// 創建長度為 N 的數組 res 并初始化為 0int[] res = new int[N];// 讀取 n 條線段的左右端點信息for (int i = 0; i < n; i++) {int l = scanner.nextInt();int r = scanner.nextInt();// 對線段中點對應的數組元素加 1res[l + r]++;}// 構建前綴和數組for (int i = 1; i < N; i++) {res[i] += res[i - 1];}// 處理 m 個查詢區間for (int i = 1; i <= m; i++) {int L = scanner.nextInt();int R = scanner.nextInt();// 將查詢區間的左右端點乘以 2L *= 2;R *= 2;int result;// 處理左端點為 0 的邊界情況if (L == 0) {result = res[R];} else {result = res[R] - res[L - 1];}// 輸出結果System.out.println(result);}scanner.close();}
}    

后面的兩道題,咱時間有限,就先跳過啦(~ ̄▽ ̄)~

等后續打國賽時,在拐回來寫寫。

當然大家有好的代碼、解析,也可以發給我,讓我瞅瞅。( ?? ω ?? )?,我貼上去。

知識點:

一、向量、點乘、叉乘

(AI整理)

1、向量:
由來:

早在古希臘時期,數學家與物理學家已經意識到某些量(如力、速度)兼具大小和方向。此時
已經蘊含了向量,但此時并未形成明確的概念與理論。

17世紀笛卡爾創建解析幾何后,點的位置可用坐標來表示,線段的長度和方向可通過坐標差量化。
這為向量的代數表達,奠定了基礎。

后來經過負數、四元數的啟發、線性擴張論...等幾代人努力與知識的迭代,向量才最終別確定下來。

定義:

?

基本屬性:

?

常見運算:

?

2、點乘:

不要問,為啥叫點乘,這是一個非常可愛的問題 --> 因為兩向量之間用 “點號” 相乘。

定義:

兩向量之間相乘,結果為標量。

?

應用:
  • 判斷兩條邊之間,是鈍角(負數)、直角(0)、還是銳角(正數)
  • 一條邊在另一條邊上映射的長度
  • 計算力的做功。
3、叉乘:

也不要問,為啥叫叉乘,這是一個非常可愛的問題 --> 因為兩向量之間用 “叉號” 相乘。

二維:

?

三維:
?應用:

切記,判斷點時,叉乘邊的方向很重要。點的那條邊,放在第二個。

求平行四邊形與三角形的面積:

二維 兩向量叉乘,求的是平行四邊形的面積。除于2,求的是三角形。

點與直線的關系:

?

線段相交的檢測:

?

點與直線關系,詳解!!?

二、浮點數比較

在編程中,通常不用==號,來進行浮點數比較。因為會出現精度誤差。即便在數學中相等,在計算機中也不一定相等。

abs(a-b)<1e-6

通常用小于1e-6來測試差值。

1e-6在通常情況下是夠用的,
它既不是那么嚴格(把本應該相同的數,判為不同)
它也不是那么寬松(把本不同的數,判為相同)

三、map與unordered_map

map底層為紅黑樹,unordered_map底層為哈希表

or,map(O(logN))的效率皆低于unordered_map(O(1))。

四、極大值(32位、64位、16進制)

  • INT32_MAX?是 32 位有符號整數的最大值,為?2,147,483,647。(2.15 × 10?)
  • 0x3f3f3f3f3f3f3f3f:轉換為十進制為:1,082,367,756,170,655,743。(約 1.08 × 101?)
  • INT64_MAX:約 9.22 × 101?。

INT32_MAX是32位,標準最大值。
INT64_MAX是64位下,標準最大值。
0x3f3f3f3f3f3f3f3f,常常被歸納于“偽最大值”,它即起到最大值的作用,又能適當的相加。在圖、樹中,常被賦予權值,表示不可抵達的點。

五、廣搜(BFS)與深搜(DFS)

廣搜:

(隊列)

  • 最短路徑問題,常用于判斷最短路徑問題。
  • 圖或樹的層序遍歷問題。
  • 判斷連通性。
深搜:

(遞歸、棧)

  • 路徑問題,尋找某一個點到另一個點的路徑,可能不是最短路徑。
  • 回溯問題,可用于某些需要試錯的算法(解數獨、八皇后)
  • 求解組合問題(全排列、組合等問題)DFS可以遍歷所有有解空間。
  • 拓撲排序,暫時還不熟悉

六、vector的比較方案-map

在C++中,兩個vector比較,是通過operate==,進行比較的。

先比較數組大小,在依次、逐個比較具體內容。

map可以以vector為鍵

std::map 基于紅黑樹(一種自平衡的二叉搜索樹)。會通過排序確定位置。(operate<)

且vector已經重載過(operate <) 了,比較時,自動按照字典序比較。

unordered_map不可以以vector為鍵

鍵的要求是

1、能滿足 哈希函數 轉化為 哈希值。

2、能通過operate== 進行比較

雖然vector中定義了operate==,但是沒有定義,哈希函數。

(總結:map都具備,unordered_map不能將vector轉化為哈希函數)


借鑒視頻、博客:

1、[算法]輕松掌握tarjan強連通分量?- 圖


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/899553.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/899553.shtml
英文地址,請注明出處:http://en.pswp.cn/news/899553.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CSS學習筆記6——網頁布局

目錄 一、元素的浮動屬性、清除浮動 清除浮動的其他方法 1、使用空標簽清除浮動影響 2、使用overflow屬性清除浮動 3、使用偽元素清除浮動影響 原理 overflow屬性 二、元素的定位 1、相對定位 2、絕對定位 ?編輯 3、固定定位 z-index層疊等級屬性 一、元素的浮動…

sqlalchemy:將mysql切換到OpenGauss

說明 之前python的項目使用的mysql&#xff0c;近期要切換到國產數據庫OpenGauss。 之前的方案是fastapisqlalchemy&#xff0c;測試下來發現不用改代碼&#xff0c;只要改下配置即可。 切換方案 安裝openGauss-connector-python-psycopg2 其代碼工程在&#xff1a;https:…

uniapp 獲取dom信息(封裝獲取元素信息工具函數)

在uniapp開發中&#xff0c;需要獲取到dom的信息&#xff0c;需要用到uniapp的指定方式 uni.createSelectorQuery()&#xff0c;但是每次需要用到的時候都需要很長一段的繁瑣代碼&#xff0c;本篇文章將呈現獲取dom信息方法封裝&#xff0c;話不多說&#xff0c;上菜&#xff1…

Linux之數據鏈路層

Linux之數據鏈路層 一.以太網1.1以太網幀格式1.2MAC地址1.3MTU 二.ARP協議2.1ARP協議工作流程2.2ARP協議格式 三.NAT技術四.代理服務4.1正向代理4.2反向代理 五.四大層的學習總結 一.以太網 在我們學習完了網絡層后我們接下來就要進入數據鏈路層的學習了&#xff0c;在學習完網…

MySQL的基礎語法2(函數-字符串函數、數值函數、日期函數和流程函數 )

目錄 一、字符串函數 1.常見字符串函數 ?編輯 2.字符串函數的基本使用 3.字符串函數的數據庫案例演示 二、數值函數 1.常見數值函數&#xff08;如下&#xff09;&#xff1a; 2.數值函數的基本使用 3.數值函數的數據庫案例演示 三、日期函數 1.常見的日期函數 2.日…

全新版租賃商城小程序源碼系統 源碼開源支持二開+圖文搭建教程

在互聯網商業的浪潮中&#xff0c;租賃業務憑借其獨特的優勢&#xff0c;正逐漸成為市場的新寵。對于開發者而言&#xff0c;快速搭建一個功能完備的租賃商城小程序&#xff0c;不僅能滿足市場需求&#xff0c;還能為自己的業務拓展帶來新的機遇。分享一款全新版租賃商城小程序…

Cent OS7+Docker+Dify

由于我之前安裝了Dify v1.0.0&#xff0c;出現了一些問題&#xff1a;無法刪除&#xff0c;包括&#xff1a;知識庫中的文件、應用、智能體、工作流&#xff0c;都無法刪除。現在把服務器初始化&#xff0c;一步步重新安裝&#xff0c;從0到有。 目錄 1、服務器重裝系統和配置…

OSI 七層模型和四層模型(TCP/IP 模型)

文章目錄 前言一、OSI 七層模型二、TCP/IP 四層模型三、運行協議及設備1. OSI 七層模型2. TCP/IP 四層模型3. 運行協議4. 各類設備的作用 總結 前言 OSI 七層模型和四層模型&#xff08;TCP/IP 模型&#xff09;是兩種常見的網絡協議分層架構&#xff0c;它們的主要區別如下&a…

AI的未來:機遇、挑戰與發展方向

&#x1f4dd;個人主頁&#x1f339;&#xff1a;一ge科研小菜雞-CSDN博客 &#x1f339;&#x1f339;期待您的關注 &#x1f339;&#x1f339; 1. 引言 人工智能&#xff08;AI&#xff09;已經成為當今世界最具革命性的技術之一&#xff0c;它正在深刻改變各個行業&#x…

javascript實現一個函數,將字符串中的指定子串全部替換為另一個字符串的原理,以及多種方法實現。

大白話javascript實現一個函數&#xff0c;將字符串中的指定子串全部替換為另一個字符串的原理&#xff0c;以及多種方法實現。 在JavaScript里&#xff0c;要是你想把字符串里的指定子串都替換成另外一個字符串&#xff0c;有不少方法可以實現。下面我會詳細介紹實現的原理&a…

硬件基礎--16_公式梳理

公式梳理 歐姆定律: IU/R 1.歐姆定律有局限性&#xff0c;僅適用于純電阻電路(或者說純電阻元器件&#xff0c;純電阻設備) 2.純電阻電路:消耗的電能僅轉化為熱能&#xff0c;沒有其他形式的能量轉換。 功率計算:PUI 1.導出公式:PU2 /R 2.導出公式:PI2 R 焦耳定律:QI2 Rt 1.導…

npm i 出現的網絡問題

npm i 出現的網絡問題 解決方案&#xff1a; npm config list 查看.npmrc文件中是否配置了proxy刪除.npmrc文件中的proxy&#xff0c;保存。重新執行npm i命令。 順便說說解決這個問題的心里路程 每次安裝vue的環境的時候&#xff0c;經常遇到npm安裝一些插件或者是依賴的時…

使用vue cli 5.0 在vscode中運行vue命令報錯

1、運行 vue -- version 報錯 2、在cmd 命令行 執行 vue --version 正常 3、在終端中輸入 get-ExecutionPolicy&#xff0c;查看當前權限 4、執行 set-executionpolicy remotesigned 命令設置為可用模式&#xff0c;但是報錯 5、使用管理員打開power shell 執行 G…

瑞芯微 RKrga接口 wrapbuffer_virtualaddr 使用筆記

一、源碼 官方在librga中給了很多 demo 以供參考&#xff0c;例如 imresize 操作&#xff1a; /** Copyright (C) 2022 Rockchip Electronics Co., Ltd.* Authors:* YuQiaowei <cerf.yurock-chips.com>** Licensed under the Apache License, Version 2.0 (the &qu…

Spring MVC:從歷史演變到實戰入門

1. Java Web的發展歷史與MVC模式 1.1 Model I與Model II的演進 Model I&#xff08;JSPJavaBean&#xff09; 作為早期Java Web開發的主流模式&#xff0c;其核心架構如下&#xff1a; graph LR A[客戶端] --> B[JSP頁面] B --> C{業務邏輯} C --> D[JavaBean] D -…

AI賦能,防御無界:群聯云防護如何顛覆傳統DDoS防御格局?

一、AI驅動的動態防御體系 智能流量調度 群聯云防護通過AI算法實時分析流量特征&#xff0c;動態分配清洗節點。當檢測到攻擊時&#xff0c;系統能在秒級內將流量切換至備用節點&#xff0c;避免單點過載。相較傳統高防IP依賴靜態規則&#xff0c;群聯的調度策略可減少50%的誤封…

R --- Error in library(***) : there is no package called ‘***’ (服務器非root用戶)

步驟 步驟一&#xff1a;在自己目錄下創建R包安裝路徑步驟二&#xff1a;配置用戶本地的R庫路徑步驟三&#xff1a;安裝缺失的包&#xff08;在終端&#xff09;步驟四&#xff1a;驗證安裝 步驟一&#xff1a;在自己目錄下創建R包安裝路徑 mkdir -p ~/R_libs步驟二&#xff1…

HarmonyOS NEXT狀態管理實踐

在HarmonyOS NEXT開發中&#xff0c;狀態管理是構建高效、響應式應用的核心。本文深入探討狀態管理的最佳實踐&#xff0c;結合代碼示例與案例分析&#xff0c;幫助開發者掌握這一關鍵技能。 一、狀態管理裝飾器的合理使用 HarmonyOS NEXT提供多種狀態管理裝飾器&#xff0c;…

excel 時間戳 轉日期

在Excel中&#xff0c;將時間戳轉換為日期格式&#xff0c;可以使用以下步驟和方法&#xff1a; 一、了解時間戳 時間戳&#xff08;Timestamp&#xff09;通常是從1970年1月1日&#xff08;UTC時間&#xff09;開始的秒數或毫秒數。這個時間點被稱為“Unix紀元”或“Unix時間…

Python CSV 數據分析:問題排查與解決全記錄

Python CSV 數據分析&#xff1a;問題排查與解決全記錄 前段時間&#xff0c;我接到一個任務&#xff0c;需要對公司的銷售數據進行分析。這些數據存儲在 CSV 文件里&#xff0c;本想著用 Python 處理起來會很輕松&#xff0c;結果卻狀況百出。下面&#xff0c;就跟大家講講我…