2024第十五屆藍橋杯大賽軟件賽省賽C/C++ 大學 B 組

記錄刷題的過程、感悟、題解。
希望能幫到,那些與我一同前行的,來自遠方的朋友😉


大綱:

?1、握手問題-(解析)-簡單組合問題(別人叫她 鴿巢定理)😇,感覺叫高級了

?2、小球反彈-(解析)-簡單物理問題,不太容易想

?3、好數-(解析)-簡單運用分支計算

?4、R 格式-(解析)-高精度,不是快速冪😉

?5、寶石組合-(解析)-lcm推論(gcd、lcm結合)

?6、數字接龍-(解析)-DFS(藍橋專屬、每年必有一道)

?7、拔河-(解析)-定一端,動一端😎


題目:

1、握手問題

問題描述

小藍組織了一場算法交流會議,總共有?50?人參加了本次會議。在會議上,大家進行了握手交流。按照慣例他們每個人都要與除自己以外的其他所有人進行一次握手 (且僅有一次)。但有?7?個人,這?7?人彼此之間沒有進行握手 (但這?7?人與除這?7?人以外的所有人進行了握手)。請問這些人之間一共進行了多少次握手?

注意?A?和?B?握手的同時也意味著?B?和?A?握手了,所以算作是一次握手。

答案提交

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

// 我看大家都叫他鴿巢定理(就是簡單的組合問題)
// 其實只需要枚舉一下就行了
// 只需要枚舉一下就行了
// 舉個例子:
// 給所有1~50個人,排一個編號。
// 第50個人,與其他49個人握手,
// 第49個人,與其他48個人握手。(因為第50個人,已經跟他握過了)
// ...
// 第8個人,給其他7個人握手
// 第7個人,就不能跟剩下的6個人握手了(題目:這?7?人彼此之間沒有進行握手 )
// 同理,第6個、第5個...
// 因為這個7個人之間,不能相互握手。

#include <iostream>
using namespace std;int main()
{int sum=0;for(int i=7; i<=49; ++i) sum+=i;cout<<sum<<endl;return 0;
}

2、小球反彈

問題描述

有一長方形,長為?343720 單位長度,寬為?2333332 單位長度。在其內部左上角頂點有一小球 (無視其體積),其初速度如圖所示且保持運動速率不變,分解到長寬兩個方向上的速率之比為?dx:dy=15:17。小球碰到長方形的邊框時會發生反彈,每次反彈的入射角與反射角相等,因此小球會改變方向且保持速率不變(如果小球剛好射向角落,則按入射方向原路返回)。從小球出發到其第一次回到左上角頂點這段時間里,小球運動的路程為多少單位長度?答案四舍五入保留兩位小數。

答案提交

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

其實這道題非常簡單的啦,畫個圖,就能解決了。

只要畫個圖、然后去找他的鏡像對稱就行。(不斷的補充方格就OK嘍)

咱們暫定,咱們的速度是1,于是沒t秒,運行t個單位。
最后的結果需要乘以2,比較要原路返回🔙。

#include <bits/stdc++.h>
#define ll long longusing namespace std;
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); ll t = 1;ll x=0,y=0; while(1){x=17*t;y=15*t;if(x%233333==0&&y%343720==0) break;else t++;}double len = 2*sqrt((x*x)+(y*y));printf("%.2lf",len);return 0; 
}  

3、好數

問題描述

一個整數如果按從低位到高位的順序,奇數位 (個位、百位、萬位????) 上的數字是奇數,偶數位 (十位、千位、十萬位????) 上的數字是偶數,我們就稱之為 “好數”。

給定一個正整數?N,請計算從 1 到?N?一共有多少個好數。

輸入格式

一個整數?N。

輸出格式

一個整數代表答案。

樣例輸入 1

24

樣例輸出 1

7

樣例輸入 2

2024

樣例輸出 2

150

樣例說明

對于第一個樣例,24?以內的好數有?1、3、5、7、9、21、23,一共?7?個。

評測用例規模與約定

對于?10%?的評測用例,1≤N≤100?。

對于?100%的評測用例,1≤N≤10^7 。

其實.....這道題,真的很簡單,如果做不出來,只能說,練的少。

其實就是簡單的模擬。

當然如果期間你用reverse反轉的話,一定會超時。(先把數字轉化為字符串,然后將字符串反轉一下,奇數位,必須是偶數;偶數位,必須是奇數。)

這是我在網上看的一哥們寫的,只能說分支被他玩明白了😇

#include <stdio.h>
int main()
{int n,i;scanf("%d",&n);for(;n>0;n--){for(int m=n;m>0;){if(m%2!=0)m/=10;else break;if(m%2==0)m/=10;else break;if(m==0)i++;}}printf("%d",i);return 0;
}

4、R 格式

問題描述

小藍最近在研究一種浮點數的表示方法:R?格式。對于一個大于 0 的浮點數?d,可以用?R?格式的整數來表示。給定一個轉換參數?n,將浮點數轉換為?R?格式整數的做法是:

  1. 將浮點數乘以?2^n;

  2. 四舍五入到最接近的整數。

輸入格式

一行輸入一個整數?n?和一個浮點數?d,分別表示轉換參數,和待轉換的浮點數。

輸出格式

輸出一行表示答案:d?用?R?格式表示出來的值。

樣例輸入

2 3.14

樣例輸出

13

樣例說明

3.14×22=12.56,四舍五入后為?13。

評測用例規模與約定

對于?50% 的評測用例:1≤n≤10,1≤ 將?d?視為字符串時的長度 ≤15。

對于?100% 的評測用例:1≤n≤1000,1≤ 將?d?視為字符串時的長度?≤1024;保證?d?是小數,即包含小數點。

哎,被這道題目給騙了😇,第一眼看上去,我還以為是快速冪呢。

其實本題本質上,就是一道高精度題目。

在藍橋杯中,高精度是一個高頻考點,我在最下部,高精度各種計算的模板。?::傳送門::

本題,實際上就是,不斷乘以2,當然啦,要用高精度的乘法模版乘。循環n次

當然,要先記錄一下數點的位置,然后減去。

#include <bits/stdc++.h>
using namespace std;// 定義兩個向量 A 和 B 用于存儲高精度數字
vector<int> A, B;// 函數 get 用于實現高精度乘法,將 A 和 B 相乘的結果存回 A
void get() {// 結果向量 C 的大小是 A 和 B 大小之和vector<int> C(A.size() + B.size()); // 逐位相乘并累加到 C 中for(int i = 0; i < A.size(); ++i)for(int j = 0; j < B.size(); ++j)C[i + j] += A[i] * B[j];    // 處理進位int carry = 0;for(int i = 0; i < C.size(); ++i) {carry += C[i];C[i] = carry % 10;carry /= 10;    }// 去除前導 0,保留有效數字while(C.size() > 1 && C.back() == 0) C.pop_back(); A = C;
}// 主函數
int main() {int n;string str;// 輸入轉換參數 n 和待轉換的浮點數(以字符串形式輸入)cin >> n >> str;// 將字符串反轉,方便處理小數部分reverse(str.begin(), str.end()); int pla = 0;// 找到小數點的位置for(int i = 0; i < str.size(); ++i) if(str[i] == '.') {pla = i; break;}// 其實這里能改進的,好在該數只有一個'.',因為 erase 函數的參數如果是字符,它會刪除字符串中所有等于該字符的字符。// 而我們只需要刪除一個小數點,也可使用 erase 函數的另一個重載版本,傳入位置參數// 例如:str.erase(pla, 1);// 將字符串中的數字字符轉換為整數存入向量 A,跳過小數點for(int i = 0; i < str.size(); ++i) if(str[i] != '.') A.emplace_back(str[i] - '0'); // 向量 B 初始化為 [2],用于后續的乘法操作B.emplace_back(2);// 執行 n 次乘法操作,即乘以 2 的 n 次方while(n--) get();// 進行四舍五入操作,如果小數點后一位大于等于 5,則進位if(A[pla - 1] >= 5) {int carry = 1;for(int i = pla; i < A.size(); ++i) {carry += A[i];A[i] = carry % 10;carry /= 10;if(carry == 0) break;}if(carry != 0) A.emplace_back(carry);}// 將結果向量 A 反轉回正常順序reverse(A.begin(), A.end());// 去除小數部分,因為題目要求輸出整數while(pla--) A.pop_back();// 輸出最終結果for(int i : A) cout << i;return 0;
}

5、寶石組合

輸入格式

第一行包含一個整數?N?表示寶石個數。

第二行包含?N?個整數表示?N?個寶石的 “閃亮度”。

輸出格式

輸出一行包含三個整數表示滿足條件的三枚寶石的 “閃亮度”。

樣例輸入

5
1 2 3 4 9

樣例輸出

1 2 3

評測用例規模與約定

對于?30% 的評測用例:3≤N≤100,1≤Hi≤1000。

對于?60% 的評測用例:3≤N≤2000。

對于?100%的評測用例:3≤N≤10^5,1≤Hi≤10^5 。

像這種題目,要學會做減法,(見好就收)

前提是,你要知道gcd與lcm都是怎么求的,否則一切都是白談。點擊了解?:: 傳送門?::?

直接暴力,先拿個30%的分數,“字典序列最小”,也只是聽著唬人罷了。😉

首先,我先給出30%的分數,然后在給出100%的解法。

30%

#include <bits/stdc++.h>
using namespace std;
#define int long long
int gcd(int a, int b)
{if (b == 0)return a;return gcd(b, a % b);
}
int lcm(int a, int b)
{return a * b / gcd(a, b);
}
int gcd3(int a, int b, int c)
{return gcd(gcd(a, b), c);
}
int lcm3(int a, int b, int c)
{return lcm(lcm(a, b), c);
}
signed main()
{int n;cin >> n;vector<int> a(n), b(3);for (int i = 0; i < n; i++)cin >> a[i];sort(a.begin(), a.end());int ans = 0;for (int i = 0; i < n; i++){for (int j = i + 1; j < n; j++){for (int k = j + 1; k < n; k++){int s = a[i] * a[j] * a[k] * lcm3(a[i], a[j], a[k]) / (lcm(a[i], a[j]) * lcm(a[i], a[k]) * lcm(a[j], a[k]));if (s > ans){ans = s;b[0] = a[i];b[1] = a[j];b[2] = a[k];}}}}cout << b[0] << " " << b[1] << " " << b[2];return 0;
}
100%

其實本題最難的,就是把公式給推導出來

就是把推導成gcd(a,b,c)

:: 具體的推導方法?::

當你把公式推導出來之后,gcd。

首先在輸入的時候,推導出gcd最大為多少(根據gcd的性質)

然后不斷減減。

假設sum=gcd(a,b,c),說明,a、b、c都是sum的倍數,然后題目就是根據這個推導出來的。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+5;
signed main(){// 既然公式已經推導出來了,那就直接來個大的吧// gcd(a,b,c) 最大數,就是輸入的數字int n;cin>>n;vector<int> arr(N,0);int maxN = -1;for(int i=0; i<n; ++i) {int cnt;cin>>cnt; // 輸入數據 arr[cnt]++;maxN=max(maxN,cnt);}for(int i=maxN; i>=1; --i){int num=0,cnt[3],flag=0; // flag:有幾個數字for(int sum=i; sum<N; sum+=i){if(arr[sum]!=0){for(int k=0; k<arr[sum]&&flag<3; ++k){cnt[flag++]=sum; }}if(flag==3){cout<<cnt[0]<<" "<<cnt[1]<<" "<<cnt[2];return 0;}} }return 0;
}

6、數字接龍

問題描述

小藍最近迷上了一款名為《數字接龍》的迷宮游戲,游戲在一個大小為?N×N 的格子棋盤上展開,其中每一個格子處都有著一個?0…K?1 之間的整數。游戲規則如下:

  1. 從左上角?(0,0)?處出發,目標是到達右下角?(N?1,N?1) 處的格子,每一步可以選擇沿著水平/垂直/對角線方向移動到下一個格子。

  2. 對于路徑經過的棋盤格子,按照經過的格子順序,上面的數字組成的序列要滿足:0,1,2,…,K?1,0,1,2,…,K?1,0,1,2…。

  3. 途中需要對棋盤上的每個格子恰好都經過一次(僅一次)。

  4. 路徑中不可以出現交叉的線路。例如之前有從?(0,0) 移動到?(1,1) ,那么再從?(1,0) 移動到?(0,1) 線路就會交叉。

為了方便表示,我們對可以行進的所有八個方向進行了數字編號,如下圖 2 所示;因此行進路徑可以用一個包含?0…7 之間的數字字符串表示,如下圖 1 是一個迷宮示例,它所對應的答案就是:41255214。

現在請你幫小藍規劃出一條行進路徑并將其輸出。如果有多條路徑,輸出字典序最小的那一個;如果不存在任何一條路徑,則輸出??1。

輸入格式

第一行包含兩個整數?N,K 。

接下來輸入?N?行,每行?N?個整數表示棋盤格子上的數字。

輸出格式

輸出一行表示答案。如果存在答案輸出路徑,否則輸出??1。

樣例輸入

3 3
0 2 0
1 1 1
2 0 2

樣例輸出

41255214

樣例說明

行進路徑如圖?1?所示。

評測用例規模與約定

對于?80%?的評測用例:1≤N≤5 。

對于?100%?的評測用例:1≤N≤10,1≤K≤10 。

DFS千篇一律,😇😉,好像都是這個模版耶,稍稍總結一下!嘿嘿(~ ̄▽ ̄)~?

#include <bits/stdc++.h>
using namespace std;// 定義棋盤的最大尺寸,這里設置為 15,可根據實際需求調整
const int N = 1e1+5; // 棋盤的邊長 n 和數字循環的周期 k
int n, k; // 存儲棋盤上每個格子的數字
int arr[N][N]; // 表示八個方向在 x 軸上的偏移量
int fa1[] = {-1, -1, 0, 1, 1, 1, 0, -1}; 
// 表示八個方向在 y 軸上的偏移量
int fa2[] = {0, 1, 1, 1, 0, -1, -1, -1}; // 用于標記棋盤上的格子是否已經被訪問過
bool used[N][N]; // 用于標記兩個格子之間的連線是否已經存在,防止路徑交叉
bool edge[N][N][N][N]; // 存儲當前正在探索的路徑
vector<int> res; 
// 存儲找到的字典序最小的路徑
vector<int> t; // 深度優先搜索函數
// cur_x, cur_y 表示當前所在格子的坐標
// cnt 表示當前已經走過的步數(從 1 開始計數)
void dfs(int cur_x, int cur_y, int cnt) {// 如果已經走過了 n * n - 1 步(因為起點已經算走過了)并且到達了右下角if (res.size() == n * n - 1 && cur_x == n - 1 && cur_y == n - 1) {// 如果 t 為空或者當前路徑 res 的字典序小于 tif (t.empty() || res < t) {// 更新 t 為當前路徑 rest = res;}return;}// 遍歷八個方向for (int i = 0; i < 8; ++i) {// 計算下一個格子的坐標int x = cur_x + fa1[i], y = cur_y + fa2[i];// 如果下一個格子超出了棋盤范圍,跳過if (x < 0 || x >= n || y < 0 || y >= n) continue; // 如果下一個格子已經被訪問過,跳過if (used[x][y]) continue;// 如果是斜向移動(i % 2 == 1)并且當前路徑會與已有的路徑交叉,跳過if (i % 2 == 1 && (edge[cur_x][y][x][cur_y] || edge[x][cur_y][cur_x][y])) continue; // 如果下一個格子的數字符合當前步數的要求(按照 0 到 k - 1 的循環)if (cnt % k == arr[x][y]) { // 將當前方向加入路徑res.push_back(i);// 標記下一個格子為已訪問used[x][y] = true;// 標記當前格子和下一個格子之間的連線已存在edge[cur_x][cur_y][x][y] = true;// 遞歸地繼續搜索下一個格子dfs(x, y, cnt + 1);// 回溯,撤銷對下一個格子的訪問標記used[x][y] = false;// 回溯,撤銷當前格子和下一個格子之間的連線標記edge[cur_x][cur_y][x][y] = false;// 回溯,從路徑中移除當前方向res.pop_back();} } 
}int main() {// 輸入棋盤的邊長 n 和數字循環的周期 kcin >> n >> k;// 輸入棋盤上每個格子的數字for (int i = 0; i < n; ++i)for (int j = 0; j < n; ++j) cin >> arr[i][j];// 標記起點為已訪問used[0][0] = true;// 從起點 (0, 0) 開始進行深度優先搜索,步數為 1dfs(0, 0, 1);// 如果沒有找到符合要求的路徑if (t.size() == 0) cout << -1 << endl;else {// 輸出字典序最小的路徑for (int i : t) cout << i;}return 0;
}

7、拔河

問題描述

小明是學校里的一名老師,他帶的班級共有?nn?名同學,第?ii?名同學力量值為?aiai?。在閑暇之余,小明決定在班級里組織一場拔河比賽。

為了保證比賽的雙方實力盡可能相近,需要在這?nn?名同學中挑選出兩個隊伍,隊伍內的同學編號連續:{al1,al1+1,…,ar1?1,ar1} 和?{al2,al2+1,…,ar2?1,ar2},其中?l1≤r1<l2≤r2。

兩個隊伍的人數不必相同,但是需要讓隊伍內的同學們的力量值之和盡可能相近。請計算出力量值之和差距最小的挑選隊伍的方式。

輸入格式

輸入共兩行。

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

第二行為?n?個正整數?ai?。

輸出格式

輸出共一行,一個非負整數,表示兩個隊伍力量值之和的最小差距。

樣例輸入

5
10 9 8 12 14

樣例輸出

1

樣例說明

其中一種最優選擇方式:

隊伍 1:?{a1,a2,a3},隊伍 2:{a4,a5},力量值和分別為?10+9+8=27 ,?12+14=26,差距為?∣27?26∣=1 。

評測用例規模與約定

對于?20%?的評測用例,保證?n≤50。

對于?100% 的評測用例,保證?n≤10^3,ai≤10^9 。

大腦模擬一下,就是兩個不能重疊的區間,在相互亂動

而,現在,我們要做的,就是定一個區間,動一個區間。

當然,我不知道,會不會有人擔心,這樣做,會不會漏掉某些區間。

舉個例子。

假設共長10。

(以下,看不懂沒關系,直接跳過,把代碼復制下來問AI😄)

[0,1]區間,此時紅線在2這個節點。如下代碼遍歷時,只能定以2為左端點。

以下代碼是不是無法判斷[7、8]這個區間?后來是不是會被遺忘點。

完全沒必要擔心,因為[0,1]會被記錄到set中,后續等以7為左邊端點時,還能對比。

// 雙動態,定一,動一。
#include <bits/stdc++.h> 
#define ll long long
using namespace std;
const ll N = 1e3+5,Num=0x3f3f3f3f3f3f3f3f;
ll n;
vector<ll> arr(N,0);
vector<ll> sum(N,0);
ll minNum=0x3f3f3f3f3f3f3f3f; // 天哦,原來如此。 int main(){ // 如果定義成這個了,全局該如何避免。 ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n;for(int i=1; i<=n; ++i) {cin>>arr[i];sum[i]=sum[i-1]+arr[i];		} set<ll> s;s.insert(Num); // 模擬插入最大值s.insert(-Num); // 模擬插入最小值 for(int i=2; i<=n; ++i){ // 中間線段 // 存入前綴和for(int j=1; j<=i-1; ++j) s.insert(sum[i-1]-sum[j-1]); // 左邊所有區間 // 匹配前綴和 for(int k=i; k<=n; ++k){ll k_sum = sum[k]-sum[i-1];auto it = s.lower_bound(k_sum); // 第一個大于or等于的數字// 目的是找到最相近的數minNum = min(minNum,abs(*it-k_sum));minNum = min(minNum,abs(*(--it)-k_sum)); }} cout<<minNum;return 0;
}


知識點:

1、鴿巢定理(抽屜原理)

基本原理:

常被用于證明存在性證明,和求最壞情況下的解

  • 存在性證明:連最壞情況都不存在解,所以情況也就肯定不存在解。
舉例:

其可以解釋許多有趣的現象(下文會解釋):

  • 世界上肯定有兩個人頭發數量一樣多
  • 1500人中,至少有5個人的生日相同
  • n個人之間握手,一定有兩個人握手的次數相同。
  • 任意6個人,其中至少有3個人互相不認識,或者互相認識

舉例子n個人握手問題,每個人必定會握手0~(n-1)次。所以必定有重復

具體6人問題:把這 6 個人看作 6 個頂點,每兩個頂點之間連一條邊。
如果兩個人互相認識,就把這條邊染成紅色;如果兩個人互相不認識,就把這條邊染成藍色。
那么問題就轉化為:在這個由 6 個頂點和它們之間的邊構成的圖中,一定存在一個同色的三角形(三條邊顏色相同的三角形),也就是要么有一個紅色三角形(代表三個人互相認識),要么有一個藍色三角形(代表三個人互相不認識)。

例題:

例題1:hdu1205 吃糖果
(隔板法)

假設N糖果數最多的一種糖果,S是總數-N;
如果:S>=N-1必然有解
S<N-1必然無解,?因為我們把糖果當成隔板了,S<N-1則必然這N個糖果,會存在糖果重疊。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;int K;
LL S, N, x;void solve()
{cin >> K;S = N = 0;for(int i = 1; i <= K; i ++){cin >> x;N = max(N, x);S += x;}S -= N;cout << (S >= N - 1 ? "Yes" : "No") << '\n';
}int main()
{cin.tie(0)->sync_with_stdio(false);cout.tie(0);int T = 1;cin >> T;while (T--){solve();}
}

2、高精度運算

基本概念:

高精度,通常是用來處理大的整數,如超過(int、long long)的整數的加減乘除。
通常是用string字符串或數組來儲存這些數,然后模擬手算。

常見類型:

  • 高精度高精度算法
  • 高精度高精度算法
  • 高精度高精度算法
  • 高精度低精度算法
  • 高精度循環加
  • 循環高精度乘低精度
高精度+高精度
#include <iostream>
#include <vector>
using namespace std;string add(string str1,string str2){ vector<int> A,B;// 逆序儲存,方便計算 for(int i=str1.size()-1; i>=0; --i) A.push_back(str1[i]-'0');for(int i=str2.size()-1; i>=0; --i) B.push_back(str2[i]-'0');// 相加vector<int> c;int carry=0;for(int i=0; i<A.size()||i<B.size()||carry; ++i){if(i<A.size()) carry+=A[i];if(i<B.size()) carry+=B[i];c.push_back(carry%10);carry/=10;} string str="";for(int i=c.size()-1; i>=0; --i) str+=c[i]+'0'; return str;
}int main(){string num1 = "1534";string num2 = "1534";cout<<add(num1, num2);return 0;
}
高精度-高精度
#include <iostream>
#include <vector>
using namespace std;bool cmp(vector<int> A,vector<int> B){ // true-A>=B.  false->A<B  if(A.size()!=B.size()) return A.size()>B.size(); // 個數不同的情況for(int i=A.size()-1; i>=0; --i){if(A[i]!=B[i]) return A[i]>B[i];}return true; 
}
string sub(string str1, string str2){vector<int> A,B;for(int i=str1.size()-1; i>=0; --i) A.push_back(str1[i]-'0');for(int i=str2.size()-1; i>=0; --i) B.push_back(str2[i]-'0');if(!cmp(A,B)) return "-"+sub(str2,str1); // 如果A<B,則交換位置,并加上負號vector<int> C;int borrow=0; // 結尾的數字for(int i=0; i<A.size(); ++i){borrow=A[i]-borrow; // 當前位的數字if(i<B.size()) borrow-=B[i]; // 天吶,這些都是啥玩意 C.push_back((borrow+10)%10); // 借位or不借位,的結果是多少borrow = borrow<0?1:0;	} while(C.size()!=1&&C[C.size()-1]==0){C.pop_back();}string str="";for(int i=C.size()-1; i>=0; --i){str+=to_string(C[i]);} return str;
}int main(){string num1 = "1000";string num2 = "1999";cout<<sub(num1,num2);return 0;
} 
高精度高精度算法
#include <iostream>
#include <vector>
using namespace std;
/*高精度-乘法1、算出最多有多少位2、將每個位置的數字,都乘進他該在的位置,記得用+=(模擬乘法3、設置一個借位的數字carry4、輾轉相除,找到他最終的位置5、正常取零 
*/
string mul(string str1,string str2){vector<int> A,B;for(int i=str1.size()-1; i>=0; --i) A.push_back(str1[i]-'0');for(int i=str2.size()-1; i>=0; --i) B.push_back(str2[i]-'0');vector<int> C(A.size()+B.size(),0); for(int i=0; i<A.size(); ++i)for(int j=0; j<B.size(); ++j)C[i+j]+=A[i]*B[j]; // !! 這一步,至關重要 int carry = 0;for(int i=0; i<C.size(); ++i){carry=carry+C[i];C[i]=carry%10;carry/=10; }while(C.size()!=1&&C[C.size()-1]==0) C.pop_back();string str="";for(int i=C.size()-1; i>=0; --i) str+=to_string(C[i]);return str;  
} int main(){string str1="123";string str2="456";cout<<mul(str1,str2);return 0;
}  
高精度除于高精度
#include <iostream>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
// 注:寫的過程,需要頭腦清晰
/*本題需要幾個函數除法的實現需要借助(sub減法模擬除法、cmp比較大小 既然是除數了,必然有除數(),也必然存在余數(0or具體的數) 他們都各自用一個vector表示。注意,不要忽略前綴為0的情況用減法模擬除法。 
*/bool cmp(vector<int> v1, vector<int> v2){ // 逆序存入,true代表v1>=v2 , false:v1<v2 if(v1.size()!=v2.size()) return v1.size()>v2.size();for(int i=v1.size()-1;  i>=0; --i)if(v1[i]!=v2[i]) return v1[i]>v2[i];return true; 
}
vector<int> sub(vector<int> v1, vector<int> v2){ // v1>=v2 vector<int> c;int borrow=0; for(int i=0; i<v1.size(); ++i){borrow=v1[i]-borrow; // 借if(i<v2.size()) borrow-=v2[i]; c.push_back((borrow+10)%10);borrow=borrow<0?1:0; }while(c.size()>1&&c.back()==0) c.pop_back();return c;
}string div(string str1, string str2, string& rs){ vector<int> A,B; for(int i=str1.size()-1; i>=0; --i) A.push_back(str1[i]-'0');for(int i=str2.size()-1; i>=0; --i) B.push_back(str2[i]-'0');vector<int> C; // 最后開頭可能會產生0 vector<int> cur; // 存放for(int i=str1.size()-1; i>=0; --i){cur.insert(cur.begin(),A[i]);  while(cur.size()>1&&cur.back()==0) cur.pop_back(); // 放入 int t=0;while(cmp(cur,B)){cur=sub(cur,B);t++;}C.push_back(t);} // 這一步反轉很重要reverse(C.begin(),C.end()); while(C.size()>1&&C.back()==0) C.pop_back();string str=""; for(int i=C.size()-1; i>=0; --i) str+=to_string(C[i]);string r="";for(int i=cur.size()-1; i>=0; --i) r+=to_string(cur[i]);rs=r;return str; 
}int main(){// 高精度除數string s1="1234";string s2="23";string remainer; cout<<div(s1,s2,remainer)<<endl;cout<<remainer<<endl; return 0; 
} 

3、快速冪

簡單復習一下,傳送門?:: 快速冪?::

#include <iostream>
using namespace std;
int main(){ // 求3^45 int base=3;int exponent=3;int result=1;while(exponent){if(exponent&1) result*=base;base*=base;  exponent>>=1; }cout<<result;
} 

4、最大公約數(gcd)與最小公倍數(lca)

最大公約數,就是兩個數,共有最大的因數

lcm是最小公倍數 :: 詳細解法 ::

定理:a、b 兩個數的最小公倍數(lcm)乘以它們的最大公約數(gcd)等于 a 和 b 本身的乘積。

如:gcd(a,b) * lcm(a,b)=a*b

#include <iostream>
using namespace std;int gcd(int a,int b){ // 最大公約數 return b!=0?gcd(b,a%b):a;
}int main(){ // 我的天吶,簡直了int num1=10,num2=8; cout<<gcd(num1,num2)<<endl; // 最大公約數cout<<num1*num2/gcd(num1,num2); // 最小公倍數 return 0;
} 

5、gcd與lcm推導

總結:

通過質因數分解和指數分析,我們發現:

  • 所有質因數的最小指數相乘,就是三個數的最大公約數(GCD)
  • 你在網上列舉其他例子也是這樣😄,我私下推導過。


借鑒博客:

1、算法學習筆記(25):鴿巢原理(抽屜原理)

2、拔河

3、差分具體用法


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

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

相關文章

HTML應用指南:利用POST請求獲取三大運營商5G基站位置信息(一)

在當前信息技術迅猛發展的背景下,第五代移動通信(5G)技術作為新一代的無線通信標準,正逐步成為推動社會進步和產業升級的關鍵驅動力。三大電信運營商(中國移動、中國聯通、中國電信)在全國范圍內的5G基站部署,不僅極大地提升了網絡性能,也為智能城市、物聯網、自動駕駛…

C++學習之線程

目錄 1.進程和線程的概念 2.線程內核三級映射 3.線程優缺點 4.創建線程和獲取線程ID的函數 5.創建子線程 6.循環創建N個子線程 7.子線程傳參地址錯誤演示分析 8.主、子線程共享全局變量、堆空間 9.線程退出 10.pthread join回收線程退出值 11.pthread_cancel 12.殺死…

element-plus中,表單校驗的使用

目錄 一.案例1&#xff1a;給下面的表單添加校驗 1.目的要求 2.步驟 ①給需要校驗的el-form-item項&#xff0c;添加prop屬性 ②定義一個表單校驗對象&#xff0c;里面存放了每一個prop的檢驗規則 ③給el-form組件&#xff0c;添加:rules屬性 ④給el-form組件&#xff0…

團體設計程序天梯賽L2-025 # 分而治之

文章目錄 題目解讀輸入格式輸出格式 思路Ac Code參考 題目解讀 在戰爭中&#xff0c;我們希望首先攻下敵方的部分城市&#xff0c;使其剩余的城市變成孤立無援&#xff0c;然后再分頭各個擊破。為此參謀部提供了若干打擊方案。本題就請你編寫程序&#xff0c;判斷每個方案的可…

Arduino示例代碼講解:Knock Sensor 敲擊感知器

Arduino示例代碼講解:Knock Sensor 敲擊感知器 Knock Sensor 敲擊感知器功能概述硬件部分:軟件部分:代碼逐行解釋定義常量定義變量`setup()` 函數`loop()` 函數工作原理Knock Sensor 敲擊感知器 這段代碼是一個Arduino示例程序,用于檢測敲擊聲。它通過讀取一個壓電元件(p…

【百日精通JAVA | SQL篇 | 第三篇】 MYSQL增刪改查

SQL得最核心就是增刪改查 一個后端開發&#xff0c;在工作中&#xff0c;最常見的場景就是CRUD。 插入數據 insert into student values (1,zhangsan); 指定列插入數據 同時多個列明之間使用逗號&#xff0c;來分割 insert into student (name) values (zhaoliu); 這個黑框…

ggscitable包通過曲線擬合深度挖掘一個陌生數據庫非線性關系

很多新手剛才是總是覺得自己沒什么可以寫的&#xff0c;自己不知道選什么題材進行分析&#xff0c;使用scitable包ggscitable包后這個完全不用擔心&#xff0c;選題多到你只會擔心你寫不完&#xff0c;寫得不夠快。 既往咱們使用scitable包交互效應深度挖掘一個陌生數據庫&…

ctfshow VIP題目限免 版本控制泄露源碼2

根據題目提示是版本控制泄露源碼 版本控制&#xff08;Version Control&#xff09;是一種在軟件開發和其他領域中廣泛使用的技術&#xff0c;用于管理文件或項目的變更歷史。 主流的版本控制工具&#xff1a; ?Git?&#xff1a;目前最流行的分布式版本控制系統。?SVN?&am…

2025-04-05 吳恩達機器學習5——邏輯回歸(2):過擬合與正則化

文章目錄 1 過擬合1.1 過擬合問題1.2 解決過擬合 2 正則化2.1 正則化代價函數2.2 線性回歸的正則化2.3 邏輯回歸的正則化 1 過擬合 1.1 過擬合問題 欠擬合&#xff08;Underfitting&#xff09; 模型過于簡單&#xff0c;無法捕捉數據中的模式&#xff0c;導致訓練誤差和測試誤…

如何用人工智能大模型,進行作業批改?

今天我們學習人工智能大模型如何進行作業批改。手把手學習視頻請訪問https://edu.csdn.net/learn/40402/666452 第一步&#xff0c;進入訊飛星火。打開google瀏覽器&#xff0c;輸入百度地址后&#xff0c;搜索”訊飛星火”&#xff0c;在搜索的結果中&#xff0c;點第一個訊飛…

C++學習筆記之 模板|函數模板|類模板

函數模板 類模板 定義&#xff1a;函數模板是建立一個通用函數&#xff0c;它所用到的數據的類型&#xff08;包括返回值類型、形參類型、局部變量類型 &#xff09;可以不具體指定&#xff0c;而是用一個虛擬的類型來代替&#xff08;用標識符占位&#xff09;&#xff0c;在…

正則入門到精通

? 一、正則表達式入門? 正則表達式本質上是一串字符序列&#xff0c;用于定義一個文本模式。通過這個模式&#xff0c;我們可以指定要匹配的文本特征。例如&#xff0c;如果你想匹配一個以 “abc” 開頭的字符串&#xff0c;正則表達式可以寫作 “^abc”&#xff0c;其中 …

對備忘錄模式的理解

對備忘錄模式的理解 一、場景1、題目【[來源](https://kamacoder.com/problempage.php?pid1095)】1.1 題目描述1.2 輸入描述1.3 輸出描述1.4 輸入示例1.5 輸出示例 2、理解需求 二、不采用備忘錄設計模式1、代碼2、問題3、錯誤的備忘錄模式 三、采用備忘錄設計模式1、代碼1.1 …

86.方便的double轉string屬性 C#例子 WPF例子

在C#開發中&#xff0c;屬性封裝是一種常見的設計模式&#xff0c;它可以幫助我們更好地控制數據的訪問和修改&#xff0c;同時提供更靈活的功能擴展。今天&#xff0c;我們就來探討一個簡單而優雅的屬性封裝示例&#xff1a;Power 和 PowerFormatted。 1. 問題背景 在實際開…

bun 版本管理工具 bum 安裝與使用

在使用 node 的過程中&#xff0c;我們可能會因為版本更新或者不同項目的要求而頻繁切換 node 版本&#xff0c;或者是希望使用更簡單的方式安裝不同版本的 node&#xff0c;這個時候我們一般會用到 nvm 或者類似的工具。 在我嘗試使用 bun 的時候&#xff0c;安裝前第一個想到…

GRE,MGRE

GRE&#xff1a;靜態過程&#xff0c;有局限性 R1 &#xff1a; [r1]interface Tunnel 0/0/0 --- 創建一個虛擬的隧道接口 [r1-Tunnel0/0/0]ip address 192.168.3.1 24 --- 給隧道接口分配一個 IP 地址 [r1-Tunnel0/0/0]tunnel-protocol gre --- 定義接口的封裝方式 [r1-Tun…

游戲無法啟動?XINPUT1_3.dll 丟失的終極解決方案

當你興奮地啟動一款新游戲時&#xff0c;突然彈出一個錯誤提示——‘程序無法啟動&#xff0c;因為計算機中丟失 XINPUT1_3.dll’。這種問題在 PC 玩家中非常常見&#xff0c;尤其是運行一些較老的游戲時。XINPUT1_3.dll 是 DirectX 運行庫的關鍵組件&#xff0c;缺失會導致游戲…

用大語言模型學文學常識

李白的詩句“右軍本清真”中的“清真”并非指伊斯蘭教信仰&#xff0c;而是對王羲之&#xff08;王右軍&#xff09;人格和藝術境界的贊美。以下是對這一問題的詳細分析&#xff1a; “清真”的古代含義 在魏晉至唐代的語境中&#xff0c;“清真”一詞多用于形容人的品格高潔、…

css炫酷的3D水波紋文字效果實現詳解

炫酷的3D水波紋文字效果實現詳解 這里寫目錄標題 炫酷的3D水波紋文字效果實現詳解項目概述技術棧核心實現1. 基礎布局2. 漸變背景3. 文字效果實現3.1 基礎樣式3.2 文字漂浮動畫 4. 水波紋效果4.1 模糊效果4.2 水波動畫 5. 交互效果 技術要點項目難點與解決方案總結 項目概述 在…

八、重學C++—動態多態(運行期)

上一章節&#xff1a; 七、重學C—靜態多態&#xff08;編譯期&#xff09;-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/146999362?spm1001.2014.3001.5502 本章節代碼&#xff1a; cpp/dynamicPolymorphic.cpp CuiQingCheng/cppstudy - 碼云 - 開源中…