數論——同余問題全家桶3 __int128和同余方程組

數論——同余問題全家桶3 __int128和同余方程組

  • 快速讀寫和__int128
    • 快速讀寫
    • `__int128`
  • 中國剩余定理和線性同余方程組
    • 中國剩余定理(CRT)
    • 中國剩余定理OJ示例
      • 模板題曹沖養豬 - 洛谷
      • 模板題猜數字 - 洛谷
    • 擴展中國剩余定理
    • 擴展中國剩余定理OJ示例
      • 模板題擴展中國剩余定理(EXCRT) - 洛谷
      • NOI2018 屠龍勇士

快速讀寫和__int128

這塊算是補充知識點,但僅作為高精度算法的臨時替代,在有的題若使用__int128也會溢出,則只能用高精度算法。

雖然在 99% 的題目中,scanf 以及 printf 來處理輸入和輸出已經足夠快了。但是,如果輸入和輸出的規模特別龐大,或者出題人卡常,scanfprintf 也是會超時的,這個時候就需要更加快速的讀寫方式。

同樣的,雖然在 99% 的題目中,long long 已經足夠我們應付較大的整數。但是,如果題目中數的范圍過大,相乘也是有可能超過 long long 的最大范圍。如果只是大一點點,此時可以用 __int128 來存儲。

快速讀寫

快速讀寫有很多種版本,接下來要介紹一種容易實現且夠用的版本 - getchar/putchar 結合秦九韶算法。

前置知識:

  1. 在計算機的視角,所有的整數其實是一個一個的字符串,每個數拆開看就是一個一個字符。因此,對于一個整數,可以當成字符串,一個一個字符的輸入進來。同理,輸出一個整數的時候,也可以當成字符串,一個一個字符的輸出。

  2. getchar/putchar 這種輸入輸出方式相較于 scanf/printf 而言,速度更快。

于是,就可以利用 getchar 將字符轉換成整數輸入,利用 putchar 將整數轉換成字符輸出。

如果這種方式還是超時,那就把 getchar 換成 getchar_unlocked。如果換完之后還是超時,那就是毒瘤題,可以忽視,或者就是算法本身的時間復雜度有問題。

但是,getchar_unlocked 只能在 Linux 系統下使用,因此要慎用。

這里通過模板題進行檢測:

P10815 【模板】快速讀入 - 洛谷

#include<bits/stdc++.h>
using namespace std;inline int read(){int flag=1,ans=0;//這個函數只有在linux操作系統下的gcc系列編譯器才能使用 //當然,洛谷也能使用,不然最后一個樣例無法通過 char ch=getchar_unlocked();//一般編譯器用這個 
//	char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar_unlocked();
//		ch=getchar();}while(ch>='0'&&ch<='9'){ans=ans*10+ch-'0';ch=getchar_unlocked();
//		ch=getchar();}return ans*flag; 
}inline void print(int a){if(a<0){putchar('-');a=-a;}if(a>9)print(a/10);putchar(a%10+'0');
}int main() {int n=read();int sum=0,x;while(n--){x=read();sum+=x;}print(sum);return 0;
}

__int128

【更大的整數__int128】

__int128 就是占用 128 字節的整數存儲類型,范圍就是 ? 2 127 ~ 2 127 ? 1 -2^{127} \sim 2^{127} - 1 ?21272127?1

? 170141183460469231731687303715884105728 ~ 170141183460469231731687303715884105727 -170141183460469231731687303715884105728\\\sim170141183460469231731687303715884105727 ?170141183460469231731687303715884105728170141183460469231731687303715884105727

170 1411 8346 0469 2317 3168 7303 7158 8410 5727//39位
  • 對比int的范圍 ? 2 32 ~ 2 32 ? 1 -2^{32} \sim 2^{32} - 1 ?232232?1,即 ? 2147483648 ~ 2147483647 -2147483648\sim2147483647 ?21474836482147483647

    無符號情況下 0 ~ 4294967295 0\sim 4294967295 04294967295

  • long long ? 2 64 ~ 2 64 ? 1 -2^{64} \sim 2^{64} - 1 ?264264?1,即 ? 9223372036854775808 ~ 9223372036854775807 -9223372036854775808\sim9223372036854775807 ?92233720368547758089223372036854775807

    無符號情況下 0 ~ 18446744073709551615 0\sim18446744073709551615 018446744073709551615

  • 如果使用了 unsigned __int128,則范圍變成 0 ~ 2 128 0 \sim 2^{128} 02128,即約 39 位數。
    0 ~ 340282366920938463463374607431768211455 0\sim 340282366920938463463374607431768211455 0340282366920938463463374607431768211455

當數據范圍超過 long long,但是還不足以用上高精度算法的時候,用 __int128 是個不錯的選擇。

但是,__int128 是不能直接用 cincoutscanf 以及 printf 輸入或者輸出的。只能按照字符的方式輸入輸出,也就是我們剛剛學習的快速讀寫的方式。不過,當讀入進來之后,用法和普通的整型變量一致。

__int128的使用示例(需要在gcc系IDE使用,例如Devc++):

#include<bits/stdc++.h>
using namespace std;
typedef unsigned __int128 uint;
typedef __int128 _int;inline void print(uint n){if(n>9)print(n/10);putchar(n%10+'0');
}inline void print(_int n){if(n<0){putchar('-');n=-n;}if(n>9)print(n/10);putchar(n%10+'0');
}inline _int read(){_int flag=1,ans=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){ans=ans*10+ch-'0';ch=getchar();}return ans*flag; 
}void f1(){_int mmax=(_int(1)<<127)-1;print(mmax);cout<<endl;_int mmin=(_int(1)<<127);print(mmin+1);//無法直接輸出-2^128 cout<<endl;
}void f2(){uint mmax=~uint(0);print(mmax);cout<<endl;
}void f3(){_int a=114514;print(a);cout<<endl;a=read();print(a);cout<<endl;a+=3;print(a);cout<<endl;a-=486;print(a);cout<<endl;a*=1435;print(a);cout<<endl;a/=1435;print(a);cout<<endl;a%=10007;print(a);cout<<endl;
}int main() {
//	f1();
//	f2();f3();return 0;
}

__int128 再好用,缺陷也很多:

  1. 不通用。 __int128 并沒有在任何一個 c++ 標準中嚴格定義,所以目前它只是 GCC 系列編譯器的專屬。目前測試,只在 Linux 系統下能夠正常使用,在其他編譯器例如MSVC不能使用。因此如果要使用,就要看比賽中的編譯器,是否是 Linux。

  2. 不方便。 __int128 目前是不支持直接讀入、輸出的。也就是無法用 cincoutscanf 以及 printf 輸入或者輸出這種類型的數。只能按照字符的方式輸入輸出,也就是我們剛剛學習的快速讀寫的方式。

  3. 空間大,速度慢。 __int128 占用了 16 個字節來存,空間超限的風險顯著增加。

但是,在有些題目中,__int128 還是足夠我們使用的。

中國剩余定理和線性同余方程組

引入線性同余方程組:南北朝時期《孫子算經》中有個問題:有物不知其數,三三數之剩二,五五數之剩三,七七數之剩二。問物幾何?

用數學公式翻譯過來就是一個線性同余方程組:

{ x ≡ 2 ( mod? 3 ) x ≡ 3 ( mod? 5 ) x ≡ 2 ( mod? 7 ) \begin{cases} x \equiv 2(\text{mod } 3) \\ x \equiv 3(\text{mod } 5) \\ x \equiv 2(\text{mod } 7) \end{cases} ? ? ??x2(mod?3)x3(mod?5)x2(mod?7)?

線性同余方程組:求這個方程組的最小非負整數解。

{ x ≡ r 1 ( mod? m 1 ) x ≡ r 2 ( mod? m 2 ) ? x ≡ r n ( mod? m n ) \begin{cases} x \equiv r_1(\text{mod } m_1) \\ x \equiv r_2(\text{mod } m_2) \\ \vdots \\ x \equiv r_n(\text{mod } m_n) \end{cases} ? ? ??xr1?(mod?m1?)xr2?(mod?m2?)?xrn?(mod?mn?)?

中國剩余定理(CRT)

前提:所有的模數 m 1 , m 2 , . . . , m n m_1, m_2, ..., m_n m1?,m2?,...,mn? 兩兩互質。因此中國剩余定理的使用比較局限。

原理:中國剩余定理是基于“構造法”得出的結果。以下給出 n = 3 n = 3 n=3 的構造過程, n n n 等于任意數的構造過程是一樣的。

對于這個方程組:
{ x ≡ r 1 ( mod? m 1 ) x ≡ r 2 ( mod? m 2 ) x ≡ r 3 ( mod? m 3 ) \begin{cases} x \equiv r_1 (\text{mod } m_1) \\ x \equiv r_2 (\text{mod } m_2)\\x \equiv r_3 (\text{mod } m_3) \end{cases} ? ? ??xr1?(mod?m1?)xr2?(mod?m2?)xr3?(mod?m3?)?

{ x m o d m 1 = r 1 x m o d m 2 = r 2 x m o d m 3 = r 3 \begin{cases}x\bmod m_1=r_1\\x\bmod m_2=r_2\\x\bmod m_3=r_3\end{cases} ? ? ??xmodm1?=r1?xmodm2?=r2?xmodm3?=r3??

M = m 1 × m 2 × m 3 M = m_1 \times m_2 \times m_3 M=m1?×m2?×m3?,構造解: x = C 1 + C 2 + C 3 x = C_1 + C_2 + C_3 x=C1?+C2?+C3?,其中:

  • C 1 mod? m 1 = r 1 , C 1 mod? m 2 = 0 , C 1 mod? m 3 = 0 C_1 \text{ mod } m_1 = r_1,\ C_1 \text{ mod } m_2 = 0,\ C_1 \text{ mod } m_3 = 0 C1??mod?m1?=r1?,?C1??mod?m2?=0,?C1??mod?m3?=0

  • C 2 mod? m 1 = 0 , C 2 mod? m 2 = r 2 , C 2 mod? m 3 = 0 C_2 \text{ mod } m_1 = 0, \ C_2 \text{ mod } m_2 = r_2, \ C_2 \text{ mod } m_3 = 0 C2??mod?m1?=0,?C2??mod?m2?=r2?,?C2??mod?m3?=0

  • C 3 mod? m 1 = 0 , C 3 mod? m 2 = 0 , C 3 mod? m 3 = r 3 C_3 \text{ mod } m_1 = 0, \ C_3 \text{ mod } m_2 = 0, \ C_3 \text{ mod } m_3 = r_3 C3??mod?m1?=0,?C3??mod?m2?=0,?C3??mod?m3?=r3?

這樣 x m o d m 1 = C 1 m o d m 1 + C 2 m o d m 1 + C 3 m o d m 1 = r 1 x\bmod m1 = C_1\bmod m1+C_2\bmod m1+C_3\bmod m_1=r_1 xmodm1=C1?modm1+C2?modm1+C3?modm1?=r1?,其他 m 2 m2 m2 m 3 m3 m3同理。

因此只要能構造出這樣的 x x x,那么 x x x 就是我們要的解。

C 1 C_1 C1? C 2 C_2 C2? C 3 C_3 C3?的構造方式:

  • C 1 = r 1 × m 2 × m 3 × ( m 2 × m 3 ) ? 1 , C_1 = r_1 \times m_2 \times m_3 \times (m_2 \times m_3)^{-1}, C1?=r1?×m2?×m3?×(m2?×m3?)?1,

    $(m_2 \times m_3)^{-1} 為模 為模 為模m_1 意義下的逆元, 意義下的逆元, 意義下的逆元,m_2 \times m_3 \times (m_2 \times m_3)^{-1}\bmod m_1 最后的結果是 1 。所以 最后的結果是1。所以 最后的結果是1。所以C_1\bmod m_1=r_1 , , C_1\bmod m_2=C_1\bmod m_3=0$。

  • C 2 = r 2 × m 1 × m 3 × ( m 1 × m 3 ) ? 1 , C_2 = r_2 \times m_1 \times m_3 \times (m_1 \times m_3)^{-1}, C2?=r2?×m1?×m3?×(m1?×m3?)?1, 其中 $(m_1 \times m_3)^{-1} 為模 為模 為模m_1$意義下的逆元。

  • C 3 = r 3 × m 1 × m 2 × ( m 1 × m 2 ) ? 1 , C_3 = r_3 \times m_1 \times m_2 \times (m_1 \times m_2)^{-1}, C3?=r3?×m1?×m2?×(m1?×m2?)?1, 其中 $(m_1 \times m_2)^{-1} 為模 為模 為模m_1$意義下的逆元。

x x x加減 M M M的若干倍時,依舊是滿足方程,因此最小非負整數解就是
( x mod? M + M ) mod? M (x \text{ mod } M + M) \text{ mod } M (x?mod?M+M)?mod?M

整個方程的通解是 x + k M x+kM x+kM

以《孫子算經》中的問題為例:
{ x ≡ 2 ( mod? 3 ) x ≡ 3 ( mod? 5 ) x ≡ 2 ( mod? 7 ) \begin{cases} x \equiv 2(\text{mod } 3) \\ x \equiv 3(\text{mod } 5) \\ x \equiv 2(\text{mod } 7) \end{cases} ? ? ??x2(mod?3)x3(mod?5)x2(mod?7)?

  1. 計算每一個方程的 C i C_i Ci?
    C 1 = r 1 × m 2 × m 3 × ( m 2 × m 3 ) ? 1 = 2 × 5 × 7 × 35 ? 1 ( mod? 3 ) = 2 × 5 × 7 × 2 = 140 C_1 = r_1 \times m_2 \times m_3 \times (m_2 \times m_3)^{-1} = 2 \times 5 \times 7 \times 35^{-1}(\text{mod } 3) = 2 \times 5 \times 7 \times 2 = 140 C1?=r1?×m2?×m3?×(m2?×m3?)?1=2×5×7×35?1(mod?3)=2×5×7×2=140
    C 2 = r 2 × m 1 × m 3 × ( m 1 × m 3 ) ? 1 = 3 × 3 × 7 × 21 ? 1 ( mod? 5 ) = 3 × 3 × 7 × 1 = 63 C_2 = r_2 \times m_1 \times m_3 \times (m_1 \times m_3)^{-1} = 3 \times 3 \times 7 \times 21^{-1}(\text{mod } 5) = 3 \times 3 \times 7 \times 1 = 63 C2?=r2?×m1?×m3?×(m1?×m3?)?1=3×3×7×21?1(mod?5)=3×3×7×1=63
    C 3 = r 3 × m 1 × m 2 × ( m 1 × m 2 ) ? 1 = 2 × 3 × 5 × 15 ? 1 ( mod? 7 ) = 2 × 3 × 5 × 1 = 30 C_3 = r_3 \times m_1 \times m_2 \times (m_1 \times m_2)^{-1} = 2 \times 3 \times 5 \times 15^{-1}(\text{mod } 7) = 2 \times 3 \times 5 \times 1 = 30 C3?=r3?×m1?×m2?×(m1?×m2?)?1=2×3×5×15?1(mod?7)=2×3×5×1=30

  2. 計算結果: x = ( 140 + 63 + 30 ) mod? 105 = 233 mod? 105 = 23 x = (140 + 63 + 30) \text{ mod } 105 = 233 \text{ mod } 105 = 23 x=(140+63+30)?mod?105=233?mod?105=23

推廣 n n n取任意數的時候,構造方式也是同理。

  • C 1 = r 1 × m 2 × m 3 × … × m n × ( m 2 × m 3 × … × m n ) ? 1 C_1 = r_1 \times m_2 \times m_3 \times \ldots \times m_n \times (m_2 \times m_3 \times \ldots \times m_n)^{-1} C1?=r1?×m2?×m3?××mn?×(m2?×m3?××mn?)?1,
  • C 2 = r 2 × m 1 × m 3 × … × m n × ( m 1 × m 3 × … × m n ) ? 1 C_2 = r_2 \times m_1 \times m_3 \times \ldots \times m_n \times (m_1 \times m_3 \times \ldots \times m_n)^{-1} C2?=r2?×m1?×m3?××mn?×(m1?×m3?××mn?)?1,
  • … \ldots
  • C n = r n × m 1 × m 2 × … × m n ? 1 × ( m 1 × m 2 × … × m n ? 1 ) ? 1 C_n = r_n \times m_1 \times m_2 \times \ldots \times m_{n-1} \times (m_1 \times m_2 \times \ldots \times m_{n-1})^{-1} Cn?=rn?×m1?×m2?××mn?1?×(m1?×m2?××mn?1?)?1

m 1 , m 2 , … , m n m_1, m_2, \ldots, m_n m1?,m2?,,mn? 兩兩互質時,一定存在這樣的 C 1 , C 2 , … , C n C_1, C_2, \ldots, C_n C1?,C2?,,Cn?,因為對應的逆元是一定存在的。且通解為: X = k × lcm + x X = k \times \text{lcm} + x X=k×lcm+x,其中 lcm \text{lcm} lcm因為 m i m_i mi?全是質數,所以實際相當于整體的乘積。

總結:在算法競賽中,中國剩余定理應用的算法流程:

  1. 計算所有模數的乘積 M = m 1 × m 2 × … × m n M = m_1 \times m_2 \times \ldots \times m_n M=m1?×m2?××mn?

  2. 計算第 i i i 個方程的 c i = M m i c_i = \frac{M}{m_i} ci?=mi?M?

  3. 計算 c i c_i ci? 在模 m i m_i mi? 意義下的逆元 c i ? 1 c_i^{-1} ci?1?(擴歐算法);

  4. 最終解為 x = ∑ i = 1 n r i c i c i ? 1 ( mod? M ) x = \sum_{i=1}^n r_i c_i c_i^{-1} (\text{mod } M) x=i=1n?ri?ci?ci?1?(mod?M)

中國剩余定理OJ示例

模板題曹沖養豬 - 洛谷

P1495 【模板】中國剩余定理(CRT)/ 曹沖養豬 - 洛谷

1634:【例 4】曹沖養豬

CRT的模板題,因為數據量大,需要使用快速冪改裝的龜速乘算法來進行最后的求乘。

龜速乘是能一步出結果的乘法,拆分成若干步乘完,這樣做能最大程度保證不溢出,但犧牲了速度。

#include<bits/stdc++.h>
using namespace std;typedef long long LL;//擴展歐幾里得算法
void exgcd(LL a, LL b, LL& x, LL& y) {if (!b) {x = 1; y = 0;return;}LL x1, y1;exgcd(b, a % b, x1, y1);x = y1; y = x1 - a / b * y1;
}//龜速乘,防溢出
LL qmul(LL a, LL b, LL m) {LL ans = 0;while (b) {if (b % 2)ans = (ans%m + a%m) % m;a = (a + a) % m;b /= 2;}return ans;
}void ac() {LL n;cin >> n;vector<LL>r(n + 1, 0), m(n + 1, 1);for (LL i = 1; i <= n; i++)cin >> m[i] >> r[i];//中國剩余定理LL M = 1;for (auto& x : m)M *= x;LL ans = 0;for (LL i = 1; i <= n; i++) {LL ci = M / m[i];LL x, y;exgcd(ci, m[i], x, y);x = (x % m[i] + m[i]) % m[i];//快速冪改裝的鬼速乘算法ans = (ans % M + qmul(qmul(r[i], ci, M), x, M)) % M;}cout << ans << endl;
}int main() {ios::sync_with_stdio(false);cin.tie(0);int T = 1;//cin >> T;while (T--)ac();return 0;
}

模板題猜數字 - 洛谷

[P3868 TJOI2009] 猜數字 - 洛谷

中國剩余定理的推廣模板。題目要求的是 b i ∣ ( n ? a i ) b_i\mid (n-a_i) bi?(n?ai?),即 ( n ? a i ) m o d b i = 0 (n-a_i)\bmod b_i=0 (n?ai?)modbi?=0,將等式拆分開就是 n m o d b i ? a i m o d b i = 0 n\bmod b_i-a_i\bmod b_i=0 nmodbi??ai?modbi?=0,即 n ≡ a i ( m o d b i ) n\equiv a_i\pmod {b_i} nai?(modbi?)

因此題目要求的就是同余方程組 n ≡ a i ( m o d b i ) n\equiv a_i\pmod {b_i} nai?(modbi?)的解, n n n是未知數。

#include<bits/stdc++.h>
using namespace std;typedef long long LL;void exgcd(LL a, LL b, LL& x, LL& y) {if (!b) {x = 1; y = 0;return;}LL x1, y1;exgcd(b, a % b, x1, y1);x = y1; y = x1 - a / b * y1;
}LL qmul(LL a, LL b, LL m) {LL ans = 0;while (b) {if (b % 2)ans = (ans + a) % m;a = (a * 2) % m;b /= 2;}return ans;
}void ac() {int n;cin >> n;vector<LL>a(n + 1, 1), b(a);for (int i = 1; i <= n; i++)cin >> a[i];LL M = 1;for (int i = 1; i <= n; i++)cin >> b[i], M *= b[i];//CRT推廣LL ans = 0;for (int i = 1; i <= n; i++) {LL ci = M / b[i];LL x, y;exgcd(ci, b[i], x, y);x = (x % b[i] + b[i]) % b[i];//a[i]為負數,需要放第1個形參,否則會死循環ans = (ans + qmul(qmul(a[i], ci, M), x, M) + M) % M;}cout << ans << endl;
}int main() {ios::sync_with_stdio(false);cin.tie(0);int T = 1;//cin >> T;while (T--)ac();return 0;
}

擴展中國剩余定理

中國剩余定理只能處理所有模數兩兩互質的情況,如果模數不互質,CRT就不適用了。

【擴展中國剩余定理 - EXCRT】

同樣是求線性同余方程組:

{ x ≡ r 1 ( mod? m 1 ) x ≡ r 2 ( mod? m 2 ) ? x ≡ r n ( mod? m n ) \begin{cases} x \equiv r_1 (\text{mod } m_1) \\ x \equiv r_2 (\text{mod } m_2) \\ \vdots \\ x \equiv r_n (\text{mod } m_n) \end{cases} ? ? ??xr1?(mod?m1?)xr2?(mod?m2?)?xrn?(mod?mn?)?

思路是將任意整數 X X X 不斷迭代成最終解。

這里補充一個方程: x ≡ r 0 ( mod? m 0 ) x \equiv r_0 (\text{mod } m_0) xr0?(mod?m0?),其中 r 0 = 0 , m 0 = 1 r_0 = 0, m_0 = 1 r0?=0,m0?=1

設最終的通解為: r e t = x × m 0 + r 0 ret = x \times m_0 + r_0 ret=x×m0?+r0?,初始時 m 0 = 1 , r 0 = 0 m_0 = 1, r_0 = 0 m0?=1,r0?=0

然后依次迭代后面的方程,使的最終解 r e t ret ret 依次滿足后續的方程。

設當前取的方程為: x ≡ r i ( mod? m i ) x \equiv r_i (\text{mod } m_i) xri?(mod?mi?),即 r e t = y × m i + r i ret = y \times m_i + r_i ret=y×mi?+ri?

  1. 根據兩式右邊相等: r e t = x × m 0 + r 0 = y × m i + r i ret = x \times m_0 + r_0 = y \times m_i + r_i ret=x×m0?+r0?=y×mi?+ri?,

  2. 于是: x × m 0 ? y × m i = r i ? r 0 x \times m_0 - y \times m_i = r_i - r_0 x×m0??y×mi?=ri??r0?,

  3. 形如 a x + b y = c ax + by = c ax+by=c,其中 a = m 0 , b = m i , c = r i ? r 0 a = m_0, b = m_i, c = r_i - r_0 a=m0?,b=mi?,c=ri??r0?

  4. 根據擴歐算法,可以解出特解 x 0 , y 0 x_0, y_0 x0?,y0?。(如果無解,算法結束)

  5. 通解為 x = x 0 + b d × k x = x_0 + \frac{b}{d} \times k x=x0?+db?×k,代入最終解中: r e t = ( x 0 + b d × k ) × m 0 + r 0 ret = (x_0 + \frac{b}{d} \times k) \times m_0 + r_0 ret=(x0?+db?×k)×m0?+r0?

  6. 整理得: r e t = k ( b d × m 0 ) + ( x 0 × m 0 + r 0 ) ret = k(\frac{b}{d} \times m_0) + (x_0 \times m_0 + r_0) ret=k(db?×m0?)+(x0?×m0?+r0?),既滿足之前的方程,也滿足當前方程。

其中新的 m ′ = b d × m 0 , r ′ = x 0 × m 0 + r m' = \frac{b}{d} \times m_0, r' = x_0 \times m_0 + r m=db?×m0?,r=x0?×m0?+r

  1. 利用 r e t ret ret的表達式繼續迭代下一個方程。直到迭代完所有的方程或某個方程無解為止。

例如:

{ x ≡ 2 ( mod? 3 ) x ≡ 3 ( mod? 5 ) x ≡ 2 ( mod? 7 ) \begin{cases} x \equiv 2(\text{mod } 3) \\ x \equiv 3(\text{mod } 5) \\ x \equiv 2(\text{mod } 7) \end{cases} ? ? ??x2(mod?3)x3(mod?5)x2(mod?7)?

補上一個方程 x ≡ 0 ( mod? 1 ) x \equiv 0 (\text{mod } 1) x0(mod?1),最終解 r e t = x × 1 + 0 ret = x \times 1 + 0 ret=x×1+0

迭代第一個方程: r e t = y × 3 + 2 ret = y \times 3 + 2 ret=y×3+2

  • r e t = x × 1 + 0 = y × 3 + 2 ret = x \times 1 + 0 = y \times 3 + 2 ret=x×1+0=y×3+2,即 x ? 3 y = 2 x - 3y = 2 x?3y=2,也可看做 x + 3 y = 2 x + 3y = 2 x+3y=2

  • 利用擴歐算法得

{ x = 2 + 3 k y = 0 ? k \begin{cases}x=2+3k\\y=0-k\end{cases} {x=2+3ky=0?k?

  • 此時 r e t = k × 3 + 2 ret=k\times 3+2 ret=k×3+2 滿足第一個方程。 k k k是整數,在后續迭代中也可看成新的未知數。

迭代第二個方程: r e t = y × 5 + 3 ret = y \times 5 + 3 ret=y×5+3

  • r e t = x × 3 + 2 = y × 5 + 3 ret = x \times 3 + 2 = y \times 5 + 3 ret=x×3+2=y×5+3,即 3 x + 5 y = 1 3x + 5y = 1 3x+5y=1

  • 利用擴歐算法解得:
    { x = 2 + 5 × k y = ? 1 ? 3 × k \begin{cases} x = 2 + 5 \times k \\ y = -1 - 3 \times k \end{cases} {x=2+5×ky=?1?3×k?

  • 于是將 x x x的通解代入 r e t ret ret 中得: r e t = k × 15 + 8 ret = k \times 15 + 8 ret=k×15+8。此時 r e t ret ret 滿足前兩個方程。

迭代第三個方程: r e t = y × 7 + 2 ret = y \times 7 + 2 ret=y×7+2

  • r e t = x × 15 + 8 = y × 7 + 2 ret = x \times 15 + 8 = y \times 7 + 2 ret=x×15+8=y×7+2,即 15 x + 7 y = ? 6 15x + 7y = -6 15x+7y=?6

  • 利用擴歐算法解得:
    { x = ? 6 + 7 × k y = 12 ? 15 × k \begin{cases} x = -6 + 7 \times k \\ y = 12 - 15 \times k \end{cases} {x=?6+7×ky=12?15×k?

  • 代入 r e t ret ret 中得: r e t = k × 105 ? 82 = k × 105 + 23 ret = k \times 105 - 82 = k \times 105 + 23 ret=k×105?82=k×105+23

此時 r e t ret ret 滿足所有方程,并且 23 23 23 為最小非負整數解。

擴展中國剩余定理OJ示例

之前的OJ例如P1495 【模板】中國剩余定理(CRT)/ 曹沖養豬 - 洛谷、[P3868 TJOI2009] 猜數字 - 洛谷也能用擴展中國剩余定理解決。

模板題擴展中國剩余定理(EXCRT) - 洛谷

P4777 【模板】擴展中國剩余定理(EXCRT) - 洛谷

需要注意的點是,構造的方程 a x + b y = c ax+by=c ax+by=c c c c需要為最小整數,以及利用 a x + b y = gcd ( a , b ) ax+by=\text{gcd}(a,b) ax+by=gcd(a,b)求方程 a x + b y = c ax+by=c ax+by=c的特解時,需要使用龜速乘算法,這些都是為防止溢出需要做的操作。

#include<bits/stdc++.h>
using namespace std;typedef long long LL;LL exgcd(LL a, LL b, LL& x, LL& y) {if (!b) {x = 1; y = 0;return a;}LL x1, y1, d = exgcd(b, a % b, x1, y1);x = y1; y = x1 - a / b * y1;return d;
}LL qmul(LL a, LL b, LL m) {LL ans = 0;while (b) {if (b & 1)ans = (ans + a) % m;a = (a * 2) % m;b >>= 1;}return ans;
}void ac() {int n;cin >> n;vector<LL>a(n + 1, 0), b(a);for (int i = 1; i <= n; i++)cin >> a[i] >> b[i];//擴展中國剩余定理//ret = k*m+rLL m = 1, r = 0;for (int i = 1; i <= n; i++) {//解不定方程mx+a[i]y=b[i]-rLL x, y, d = exgcd(m, a[i], x, y), c = b[i] - r;c = (c % a[i] + a[i]) % a[i];if (c % d) {cout << -1 << endl;return;}y = a[i] / d;//y是不定方程的另一個解,不重要,于是代碼復用//加龜速乘,擦邊通關OJx = qmul(x, c / d, y);x = (x % y + y) % y;r = x * m + r;m = y * m;r = (r % m + m) % m;//ret = k*m+r,可以用m對r進行范圍限制}cout << r << endl;
}int main() {ios::sync_with_stdio(false);cin.tie(0);int T = 1;//cin >> T;while (T--)ac();return 0;
}

NOI2018 屠龍勇士

[P4774 NOI2018] 屠龍勇士 - 洛谷

這種個人感覺是真正的壓軸題或準壓軸題級別的題,題目又臭又長,還得逐句分析,其中分析還得分階段,嚴重的還有分類談論,每個階段的分析還得有聯系,不然無法流暢地翻譯成自然語言或代碼。

在實現時往往伴隨著知識點的嵌套使用,極其考驗綜合能力。

讀題:

首先是游戲規則:

  1. 1條龍,打它會使Hp會變負數,然后回血,Hp恢復到0時龍死去,否則不能死去。

    例如龍的初始Hp為 5,將血量斬殺到 -4,龍的回血 p = 2 p=2 p=2,回 2 次后龍會死去;或剛好砍到Hp位0,則龍死去。

    但如果某幾次攻擊將血量斬殺到-3,龍回血2次后血量變成1,龍就還能蹦迪。

    所以選擇的武器需要將龍的血量控制在 p p p的整數倍才能擊殺。

  2. 砍龍需要選劍,砍死龍得新劍。

然后這人想寫個腳本之類的東西掛機刷游戲,腳本原理:

  1. 選擇當前有的、傷害不大于龍Hp、同時傷害是最大的劍。沒有就選傷害最小的。

    例如Hp = 5,劍 a [ i ] = { 1 , 2 , 3 , 4 , 4 , 5 , 6 , 7 , 8 , 9 } a[i]=\{1,2,3,4,4,5,6,7,8,9\} a[i]={1,2,3,4,4,5,6,7,8,9},此時選a[5]=5的劍。

    a [ i ] = 6 , 7 a[i]={6,7} a[i]=6,7,此時選a[0]=6的劍。

  2. 對每條龍,設置固定的攻擊次數 x x x

之后就是解題思路:

  1. 確定哪條龍用哪把劍。

    既然要選劍,則劍應該有序,想到排序

    對每條龍,考慮Hp和獎勵,在劍的集合中選不大于龍的血量且傷害最大的,首先應該想到二分優化的枚舉,二分的話要考慮數組,數組需要看數據量是否支持。

    因為有消耗和獎勵,需要頻繁插入和刪除還有取出指定位置的劍,想到集合multiset,插入和取出都是 O ( log ? n ) O(\log n) O(logn)。可以選擇用upper_bound快速查找,但要注意這個成員函數找的是大于Hp的最小值,所以需要使返回的迭代器減1,邊界情況是所有劍都大于Hp。

  2. 如何確定攻擊次數 x x x

    根據題意解讀的每條龍的信息{初始血量Hp,恢復rv,劍的傷害swd,打的次數x,恢復次數y},根據游戲規則構造等式 H p ? s w d × x + r v × y = 0 Hp-swd\times x+rv\times y=0 Hp?swd×x+rv×y=0,即 s w d × x = r v × y + H p swd\times x=rv\times y+Hp swd×x=rv×y+Hp,看到這個等式想到
    s w d × x ÷ r v = y … H p swd\times x\div rv=y\dots Hp swd×x÷rv=yHp,2個等式 s w d × x = r v × y + H p swd\times x=rv\times y+Hp swd×x=rv×y+Hp s w d × x ÷ r v = y … H p swd\times x\div rv=y\dots Hp swd×x÷rv=yHp中, y y y也是未知數,所以根據這2個等式可得出同余方程 s w d × x ≡ H p ( m o d r v ) swd\times x\equiv Hp\pmod {rv} swd×xHp(modrv)

    對所有龍的同余方程組

    { s w d 1 x ≡ H p 1 ( m o d r v 1 ) s w d 2 x ≡ H p 2 ( m o d r v 2 ) … s w d n x ≡ H p n ( m o d r v n ) \begin{cases}swd_1x\equiv Hp_1\pmod {rv_1}\\swd_2x\equiv Hp_2\pmod {rv_2}\\\dots\\swd_nx\equiv Hp_n\pmod {rv_n}\end{cases} ? ? ??swd1?xHp1?(modrv1?)swd2?xHp2?(modrv2?)swdn?xHpn?(modrvn?)?

    解出 x x x的,即為攻擊次數。和之前的同余方程組不同,這個方程組的未知數帶系數,使用擴展中國剩余定理時需要注意細節。

    • 擴展中國剩余定理解同余方程組:

      約定攻擊次數 r e t ret ret,恢復力 m = r v m=rv m=rv r = H p r=Hp r=Hp

      設方程 r e t = k m + r ret=km+r ret=km+r m = 1 m=1 m=1 r = 0 r=0 r=0

      對任一方程 s w d × x ≡ H p ( m o d r v ) swd\times x\equiv Hp\pmod {rv} swd×xHp(modrv),其實就是 s w d × r e t = y × r v + H p swd\times ret=y\times rv+Hp swd×ret=y×rv+Hp,次數 x x x換成了 r e t ret ret,都表示攻擊次數。

      聯立:

      { r e t = k m + r s w d × r e t = y × r v + H p \begin{cases}ret=km+r\\swd\times ret=y\times rv+Hp\end{cases} {ret=km+rswd×ret=y×rv+Hp?

      第1個方程左右同時乘 s w d swd swd消去 r e t ret ret,并移項得

      s w d × m × k + y × r v = H p ? s w d × r swd\times m\times k+y\times rv=Hp-swd\times r swd×m×k+y×rv=Hp?swd×r,此時得到一個不定方程

      對比 A x + B y = C Ax+By=C Ax+By=C A = s w d × m A=swd\times m A=swd×m B = r v B=rv B=rv C = H p ? s w d × r C=Hp-swd\times r C=Hp?swd×r

      之后就是熟悉的流程:擴展歐幾里得算法 k k k(或者說 x x x)的通解,代入 r e t = k m + r ret=km+r ret=km+r得到新的 m m m r r r,并用它們繼續迭代其他方程。

      對比之前的擴展中國剩余定理,多個常數系數時只需要聯立方程組即可解決。

    • 細節問題:

      • 防溢出

        在乘法階段用龜速乘算法代替。同時對方程 s w d × x ≡ H p ( m o d r v ) swd\times x\equiv Hp\pmod {rv} swd×xHp(modrv) s w d × x swd\times x swd×x H p Hp Hp可以都同時先模 m m m限制大小,即 ( s w d × x m o d r v ) ≡ ( H p m o d r v ) ( m o d r v ) (swd\times x\bmod rv)\equiv {(Hp\bmod rv)}\pmod {rv} (swd×xmodrv)(Hpmodrv)(modrv)。其他地方能取模盡量取模

      • 最終結果 r e t = k m + r ret=km+r ret=km+r中的 r r r可能不是正確答案,而是只是方程組的解,此時還需要 y > 0 y>0 y>0也就是恢復次數也要大于0。

        此時對于每條龍的血量 H p Hp Hp和劍的傷害 s w d swd swd,在求攻擊次數時需為 ? H p s w d ? \lceil\frac{Hp}{swd}\rceil ?swdHp??。例如Hp為5的龍,傷害為2的劍,攻擊次數需要為 ? 5 2 ? = 3 \lceil\frac{5}{2}\rceil=3 ?25??=3,才能壓血線到負數。

        同時需要將每條龍斬到負數Hp的攻擊次數并不完全相同,此時需要取最大的次數,取方程中攻擊次數大于最大攻擊次數的特解,才能保證將所有的龍的血量砍到負數。這里假設所有龍中需要被砍的最多的次數為 max_tm \text{max\_tm} max_tm max_tm = ? Hp swd ? \text{max\_tm}=\lceil\frac{\text{Hp}}{\text{swd}}\rceil max_tm=?swdHp??

        對表示攻擊次數的方程 r e t = k m + r ret=km+r ret=km+r,需有 r e t ≥ max_tm ret\geq \text{max\_tm} retmax_tm

        • r ≥ max_tm r\geq \text{max\_tm} rmax_tm,此時 r e t = r ret=r ret=r

        • r < max_tm r<\text{max\_tm} r<max_tm,此時 r e t = ? max_tm ? r m ? × m + r ret=\lceil\frac{\text{max\_tm}-r}{m}\rceil\times m+r ret=?mmax_tm?r??×m+r

          這里 ? max_tm ? r m ? \lceil\frac{\text{max\_tm}-r}{m}\rceil ?mmax_tm?r??表示需要在最小正整數解的基礎上增加的模數 m m m的數量,這樣做是為了求能以最低的固定攻擊次數將所有的龍都壓到負數Hp的特解。

參考程序(變量名和數組名與分析對應):

#include<bits/stdc++.h>
using namespace std;typedef long long LL;LL exgcd(LL a, LL b, LL& x, LL& y) {if (!b) {x = 1; y = 0;return a;}LL x1, y1, d = exgcd(b, a % b, x1, y1);x = y1; y = x1 - a / b * y1;return d;
}LL qmul(LL a, LL b, LL m) {LL ans = 0;while (b) {if (b % 2)ans = (ans + a) % m;a = (a * 2) % m;b /= 2;}return ans;
}void ac() {int N, M;cin >> N >> M;//Hp血量,rv恢復,rd reword獎勵,swd sword砍龍時用的劍vector<LL>Hp(N + 1, 0), rv(Hp), rd(Hp),swd(Hp);multiset<LL>st;LL max_tm = 0;//max times,最難砍的龍需要的次數for (int i = 1; i <= N; i++)cin >> Hp[i];for (int i = 1; i <= N; i++)cin >> rv[i];for (int i = 1; i <= N; i++)cin >> rd[i];for (int i = 1; i <= M; i++) {LL x; cin >> x;st.insert(x);}//選擇劍for (int i = 1; i <= N; i++) {//二分auto it = st.upper_bound(Hp[i]);if (it != st.begin())--it;swd[i] = *it;max_tm = max(max_tm, (Hp[i] + swd[i] - 1) / swd[i]);st.erase(it);st.insert(rd[i]);}//確定攻擊次數//擴展中國剩余定理,初始方程ret=mx+r,m是rv,r是hp,res是攻擊次數//對應同余方程(組)swd*x % rv = HpLL m = 1, r = 0;for (int i = 1; i <= N; i++) {//Hp-swd*x+rv*y=0 得到同余方程//聯立ret=mx+r和Hp-swd*x+rv*y=0//得到不定方程 (swd-m) x + rv* y= Hp-swd*rLL A = qmul(swd[i] ,m,rv[i]), B = rv[i], C = Hp[i] - swd[i] * r;C = (C % B + B) % B;LL x, y, d = exgcd(A, B, x, y);if (C % d) {cout << -1 << endl;return;}LL g1 = B / d;x = qmul(x,C / d,g1);x = (x % g1 + g1) % g1;r = r + x * m;m = g1 * m;r = (r % m + m) % m;}//最小正整數解可能無法將所有的龍都砍到負數Hp需要求特解if (r < max_tm)r = r + (max_tm - r + m - 1) / m * m;cout << r<<endl;
}int main() {ios::sync_with_stdio(false);cin.tie(0);int T = 1;cin >> T;while (T--)ac();return 0;
}

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

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

相關文章

Python爬蟲實戰:研究MechanicalSoup庫相關技術

一、MechanicalSoup 庫概述 1.1 庫簡介 MechanicalSoup 是一個 Python 庫,專為自動化交互網站而設計。它結合了 requests 的 HTTP 請求能力和 BeautifulSoup 的 HTML 解析能力,提供了直觀的 API,讓我們可以像人類用戶一樣瀏覽網頁、填寫表單和提交請求。 1.2 主要功能特點…

祝?高考加油

以下是極為詳細的高考注意事項清單&#xff0c;涵蓋考前、考中、考后全流程&#xff0c;建議逐條核對&#xff1a; 一、考前準備 1. 證件與物品 必帶清單&#xff1a; 準考證&#xff1a;打印2份&#xff08;1份備用&#xff09;&#xff0c;塑封或夾在透明文件袋中防皺濕。身…

學習路之PHP--webman安裝及使用、webman/admin安裝

學習路之PHP--webman安裝及使用、webman/admin安裝 一、安裝webman二、運行三、安裝webman/admin四、效果五、配置Nginx反向代理&#xff08;生產環境&#xff1a;可選&#xff09;六、win10運行問題集七、使用 一、安裝webman 準備&#xff1a; PHP > 8.1 Composer > 2…

mamba架構和transformer區別

Mamba 架構和 Transformer 架構存在多方面的區別&#xff0c;具體如下&#xff1a; 計算復雜度1 Transformer&#xff1a;自注意力機制的計算量會隨著上下文長度的增加呈平方級增長&#xff0c;例如上下文增加 32 倍時&#xff0c;計算量可能增長 1000 倍&#xff0c;在處理長序…

Python爬蟲實戰:研究mechanize庫相關技術

1. 引言 隨著互聯網數據量的爆炸式增長,網絡爬蟲已成為數據采集和信息挖掘的重要工具。Python 作為一種功能強大且易于學習的編程語言,擁有豐富的爬蟲相關庫,如 Requests、BeautifulSoup、Scrapy 等。Mechanize 庫作為其中的一員,特別擅長處理復雜的表單提交和會話管理,為…

如何使用索引和條件批量更改Series數據

視頻演示 如何通過索引與布爾條件修改 pandas Series&#xff1f;實操演示來了 一、前言&#xff1a;掌握Series數據修改是數據處理的基礎 在使用Python進行數據分析時&#xff0c;Pandas庫的Series對象是最常用的結構之一。在上一個視頻中我們已經學習了如何創建Series對象&a…

CentOS 7 如何安裝llvm-project-10.0.0?

CentOS 7 如何安裝llvm-project-10.0.0&#xff1f; 需要先升級gcc至7.5版本&#xff0c;詳見CentOS 7如何編譯安裝升級gcc版本?一文 # 備份之前的yum .repo文件至 /tmp/repo_bak 目錄 mkdir -p /tmp/repo_bak && cd /etc/yum.repo.d && /bin/mv ./*.repo …

6個月Python學習計劃 Day 15 - 函數式編程、高階函數、生成器/迭代器

第三周 Day 1 &#x1f3af; 今日目標 掌握 Python 中函數式編程的核心概念熟悉 map()、filter()、reduce() 等高階函數結合 lambda 和 列表/字典 進行數據處理練習了解生成器與迭代器基礎&#xff0c;初步掌握惰性計算概念 &#x1f9e0; 函數式編程基礎 函數式編程是一種…

SpringCloud Gateway 集成 Sentinel 詳解 及實現動態監聽Nacos規則配置實時更新流控規則

目錄 一、前言二、版本選擇和適配 2.1、本文使用各組件版本2.2、官方推薦版本 三、部署sentinel-dashboard 3.1、下載 sentinel-dashboard jar包3.2、啟動 sentinel-dashboard 四、Gateway 集成 Sentinel實現控制臺配置流控規則測試 4.1、添加Gateway 集成 Sentinel 包4.2、添加…

Linux八股【1】-----虛擬內存

參考&#xff1a;小林coding 虛擬內存存在的目的&#xff1f; 為了能夠同時運行多個進程同時進程之間互不干擾 虛擬地址通過MMU找到物理地址 物理內存怎么映射的&#xff1f; 物理內存的映射方法主要有兩種&#xff0c;內存分段和內存分頁 內存分段 把程序的不同區&#…

驚艷呈現:探索數據可視化的藝術與科學

一張圖表真能勝過千言萬語&#xff1f;當超市銷售數據變成跳動的熱力圖&#xff0c;當城市交通擁堵狀況化作流動的光帶&#xff0c;數據可視化正以超乎想象的方式重塑我們認知世界的維度。但你是否想過&#xff0c;那些看似精美直觀的圖表背后&#xff0c;藏著怎樣精密的科學邏…

06-排序

排序 1. 排序的概念及其應用 1.1 排序的概念 排序&#xff1a;所謂排序&#xff0c;就是使一串記錄&#xff0c;按照其中的某個或某些關鍵字的大小&#xff0c;遞增或遞減的排列起來的操作。 穩定性&#xff1a;假定在待排序的記錄序列中&#xff0c;存在多個具有相同的關鍵…

從失效文檔到知識資產:Gitee Wiki 引領研發知識管理變革

在關鍵領域軟件研發的復雜生態中&#xff0c;知識管理正成為制約行業發展的關鍵瓶頸。隨著軟件系統規模不斷擴大、技術棧日益復雜&#xff0c;傳統文檔管理模式已難以滿足現代軟件工廠對知識沉淀、共享和傳承的需求。Gitee Wiki作為新一代知識管理平臺&#xff0c;通過技術創新…

MySQL 性能調優入門 - 慢查詢分析與索引優化基礎

MySQL 性能調優入門 - 慢查詢分析與索引優化基礎 性能問題診斷的通用思路 當數據庫出現性能問題時,切忌盲目猜測或隨意調整參數。一個科學的診斷流程通常包括: 基于數據,而非猜測 (Data-Driven, Not Guesswork):利用我們在上一篇討論的性能監控指標和建立的基線。查看哪些…

8天Python從入門到精通【itheima】-73~74(數據容器“集合”+案例練習)

目錄 73節-集合的基礎定義和操作 1.學習目標 2.為什么要用集合 3.集合的定義 4.關于集合的常用操作 【1】添加新元素&#xff1a;add方法 【2】移除元素&#xff1a;remove方法 【3】隨機取出元素&#xff1a;pop方法 【4】清空集合&#xff1a;clear方法 【5】取出兩…

國芯思辰| AD7894的優質替代方案:SC1424模數轉換器在分布式控制系統中的應用優勢

分布式控制系統將控制任務分散至多個節點&#xff0c;各節點協同工作以實現復雜的控制目標。在這一架構下&#xff0c;系統ADC提出了嚴苛要求。高精度是精準采集各類模擬信號&#xff08;如傳感器輸出的電壓、電流信號&#xff09;的基礎&#xff0c;關乎控制決策的準確性&…

Unity基礎-數學向量

Unity基礎-數學向量 二、向量相關用法 概述 向量在Unity游戲開發中扮演著重要角色&#xff0c;用于表示位置、方向、速度等。Unity提供了Vector2、Vector3等結構體來處理向量運算。 1. 向量基礎操作 1.1 向量創建和訪問 // 創建向量 Vector3 position new Vector3(1, 2,…

Neo4j 數據建模:原理、技術與實踐指南

Neo4j 作為領先的圖數據庫,其核心優勢在于利用圖結構直觀地表達和高效地查詢復雜關系。其數據建模理念與傳統關系型數據庫截然不同,專注于實體(節點)及其連接(關系)。以下基于官方文檔,系統闡述其建模原理、關鍵技術、實用技巧及最佳實踐: 一、 核心原理:以關系為中心…

volka 25個短語動詞

以下是分句分段后的內容&#xff1a; 3,000. Thats 95% of spoken English. And I am teaching you all of these words. First, Ill teach you todays words. And then youll hear them in real conversations. With my brother. Stick around until the end, because witho…

服務器中日志分析的作用都有哪些

服務器日志是用來檢測和排查可疑行為的主要工具&#xff0c;運維團隊可以通過分析和解讀日志文件&#xff0c;發現服務器中潛在的網絡安全威脅或異常活動&#xff0c;下面&#xff0c;就讓小編和大家一起來了解一下服務器中日志分析的作用都有什么吧&#xff01; 對于服務器中的…