'commit'
This commit is contained in:
3
TangDou/AcWing_TiGao/T5/QMI/1289.in
Normal file
3
TangDou/AcWing_TiGao/T5/QMI/1289.in
Normal file
@@ -0,0 +1,3 @@
|
||||
2
|
||||
1 2 3 5
|
||||
1 2 4 5
|
||||
154
TangDou/AcWing_TiGao/T5/QMI/1289.md
Normal file
154
TangDou/AcWing_TiGao/T5/QMI/1289.md
Normal file
@@ -0,0 +1,154 @@
|
||||
##[$AcWing$ $1289$. 序列的第$K$个数](https://www.acwing.com/problem/content/1291/)
|
||||
|
||||
### 一、题目描述
|
||||
$BSNY$ 在学等差数列和等比数列,当已知前三项时,就可以知道是等差数列还是等比数列。
|
||||
|
||||
现在给你 **整数** 序列的前三项,这个序列要么是等差序列,要么是等比序列,你能求出第 $k$ 项的值吗?
|
||||
|
||||
如果第 $k$ 项的值太大,对其取模 $200907$。
|
||||
|
||||
**输入格式**
|
||||
第一行一个整数 $T$,表示有 $T$ 组测试数据;
|
||||
|
||||
对于每组测试数据,输入前三项 $a,b,c$,然后输入 $k$。
|
||||
|
||||
**输出格式**
|
||||
对于每组数据,输出第 $k$ 项取模 $200907$ 的值。
|
||||
|
||||
**数据范围**
|
||||
$1≤T≤100$
|
||||
$1≤a≤b≤c≤10^9$
|
||||
$1≤k≤10^9$
|
||||
|
||||
**输入样例**
|
||||
```cpp {.line-numbers}
|
||||
2
|
||||
1 2 3 5
|
||||
1 2 4 5
|
||||
```
|
||||
**输出样例**
|
||||
```cpp {.line-numbers}
|
||||
5
|
||||
16
|
||||
```
|
||||
|
||||
### 二、$Q$:一个数列能不能即是等差数列又是等比数列?
|
||||
|
||||
#### 结论:一个数列如果是即是等差又是等比,那么它必然是一个全等数列
|
||||
|
||||
**证明**:
|
||||
设三个连续数字$a\ b \ c$,
|
||||
等差数列,所以$a+c=2b$ ①
|
||||
等比数列,所以$\frac{b}{a}=\frac{c}{b}$,所以$b^2=ac$ ②
|
||||
|
||||
将$a=2b-c$代入②
|
||||
$b^2=(2b-c)*c$
|
||||
$b^2=2bc-c^2$
|
||||
$b^2-2bc+c^2=0$
|
||||
$(b-c)^2=0$
|
||||
∴$b=c$
|
||||
|
||||
由此可知,题目中给了数列的前三项,存在可能即是等差又是等比的情况,但此时就是一个全等数列,按哪个规则进行计算都是一样的结果,题目不缺少条件。
|
||||
|
||||
### 三、题意分析
|
||||
|
||||
* **等差数列**
|
||||
公差 $d=b-a$
|
||||
第$1$项,$a+0*d$
|
||||
第$2$项,$a+1*d$
|
||||
第$3$项,$a+2*d$
|
||||
...
|
||||
第$k$项,应该是$a+(k-1)d$,这个很好求,直接求然后注意取模就行了。
|
||||
|
||||
* **等比数列**
|
||||
公比$p=\frac{b}{a}$
|
||||
第$1$项,$a*p^0$
|
||||
第$2$项,$a*p^1$
|
||||
第$3$项,$a*p^2$
|
||||
...
|
||||
第$k$项,$a*p^{k-1}=a*(\frac{b}{a})^{k-1}$
|
||||
|
||||
这东西用 **快速幂** 就行了
|
||||
|
||||
### 四、理解与思考
|
||||
数学的题,一般不会真的用代码去暴力计算,通常是推公式,证明。在完成公式的推导后,再用代码进行简单计算,比如$2022$ $CSP-J$的第二题就是一道公式的推导题,小心下细节就行了。
|
||||
|
||||
- **快速幂**:把次数依次化为$2$进制,即可迭代
|
||||
- **龟速乘**:把当前数变为$2$进制加起来,用于数据很大的情况
|
||||
|
||||
### 五、实现代码
|
||||
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define int long long
|
||||
const int MOD = 200907;
|
||||
|
||||
// 快速幂
|
||||
int qmi(int a, int b) {
|
||||
int res = 1;
|
||||
while (b) {
|
||||
if (b & 1) res = res * a % MOD;
|
||||
a = a * a % MOD;
|
||||
b >>= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
signed main() {
|
||||
int n;
|
||||
cin >> n;
|
||||
while (n--) {
|
||||
int a, b, c, k;
|
||||
cin >> a >> b >> c >> k;
|
||||
if (a + c == b * 2) // 等差
|
||||
cout << (a + (b - a) * (k - 1)) % MOD << endl; // 这个比较简单
|
||||
else // 等比
|
||||
cout << a * qmi(b / a, k - 1) % MOD << endl; // 这个需要快速幂
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 六、龟速乘版本
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define int long long
|
||||
|
||||
const int MOD = 200907;
|
||||
|
||||
// 龟速乘,快速加
|
||||
int qadd(int a, int b) {
|
||||
int res = 0;
|
||||
while (b) {
|
||||
if (b & 1) res = (res + a) % MOD;
|
||||
b >>= 1;
|
||||
a = (a + a) % MOD;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 快速幂
|
||||
int qmi(int a, int b) {
|
||||
int res = 1;
|
||||
while (b) {
|
||||
if (b & 1) res = (res * a) % MOD;
|
||||
b >>= 1;
|
||||
a = a * a % MOD;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
signed main() {
|
||||
int T;
|
||||
cin >> T;
|
||||
while (T--) {
|
||||
int a, b, c, k;
|
||||
cin >> a >> b >> c >> k;
|
||||
if (a + c == b + b)
|
||||
cout << (qadd(b - a, k - 1) + a) % MOD << endl; // 为等差即套公式,首项+公差*(项数-1)
|
||||
else
|
||||
cout << qmi(b / a, k - 1) * a % MOD << endl; // 等比数列用快速幂算末项
|
||||
}
|
||||
}
|
||||
```
|
||||
28
TangDou/AcWing_TiGao/T5/QMI/1289_1.cpp
Normal file
28
TangDou/AcWing_TiGao/T5/QMI/1289_1.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define int long long
|
||||
const int MOD = 200907;
|
||||
|
||||
// 快速幂
|
||||
int qmi(int a, int b) {
|
||||
int res = 1;
|
||||
while (b) {
|
||||
if (b & 1) res = res * a % MOD;
|
||||
a = a * a % MOD;
|
||||
b >>= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
signed main() {
|
||||
int n;
|
||||
cin >> n;
|
||||
while (n--) {
|
||||
int a, b, c, k;
|
||||
cin >> a >> b >> c >> k;
|
||||
if (a + c == b * 2) // 等差
|
||||
cout << (a + (b - a) * (k - 1)) % MOD << endl; // 这个比较简单
|
||||
else // 等比
|
||||
cout << a * qmi(b / a, k - 1) % MOD << endl; // 这个需要快速幂
|
||||
}
|
||||
}
|
||||
40
TangDou/AcWing_TiGao/T5/QMI/1289_2.cpp
Normal file
40
TangDou/AcWing_TiGao/T5/QMI/1289_2.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define int long long
|
||||
|
||||
const int MOD = 200907;
|
||||
|
||||
// 龟速乘,快速加
|
||||
int qadd(int a, int b) {
|
||||
int res = 0;
|
||||
while (b) {
|
||||
if (b & 1) res = (res + a) % MOD;
|
||||
b >>= 1;
|
||||
a = (a + a) % MOD;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 快速幂
|
||||
int qmi(int a, int b) {
|
||||
int res = 1;
|
||||
while (b) {
|
||||
if (b & 1) res = (res * a) % MOD;
|
||||
b >>= 1;
|
||||
a = a * a % MOD;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
signed main() {
|
||||
int T;
|
||||
cin >> T;
|
||||
while (T--) {
|
||||
int a, b, c, k;
|
||||
cin >> a >> b >> c >> k;
|
||||
if (a + c == b + b)
|
||||
cout << (qadd(b - a, k - 1) + a) % MOD << endl; // 为等差即套公式,首项+公差*(项数-1)
|
||||
else
|
||||
cout << qmi(b / a, k - 1) * a % MOD << endl; // 等比数列用快速幂算末项
|
||||
}
|
||||
}
|
||||
21
TangDou/AcWing_TiGao/T5/QMI/1290.cpp
Normal file
21
TangDou/AcWing_TiGao/T5/QMI/1290.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define int long long
|
||||
const int MOD = 100003;
|
||||
|
||||
int qmi(int a, int b) {
|
||||
int res = 1;
|
||||
while (b) {
|
||||
if (b & 1) res = res * a % MOD;
|
||||
a = a * a % MOD;
|
||||
b >>= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
signed main() {
|
||||
int m, n;
|
||||
cin >> m >> n;
|
||||
cout << (qmi(m, n) - m * qmi(m - 1, n - 1) % MOD + MOD) % MOD << endl;
|
||||
return 0;
|
||||
}
|
||||
37
TangDou/AcWing_TiGao/T5/QMI/1290.drawio
Normal file
37
TangDou/AcWing_TiGao/T5/QMI/1290.drawio
Normal file
@@ -0,0 +1,37 @@
|
||||
<mxfile host="Electron" modified="2023-11-13T06:26:20.100Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.3.7 Chrome/112.0.5615.204 Electron/24.5.0 Safari/537.36" etag="LmC1guNWCzKyO7h3SnAr" version="21.3.7" type="device">
|
||||
<diagram name="第 1 页" id="VIb_nIt0eGq0H4E8IJp7">
|
||||
<mxGraphModel dx="1418" dy="838" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="EC6tnr1v8_Lx4r9o5bla-1" value="1" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="240" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EC6tnr1v8_Lx4r9o5bla-2" value="2" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="200" y="240" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EC6tnr1v8_Lx4r9o5bla-3" value="3" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="300" y="240" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EC6tnr1v8_Lx4r9o5bla-4" value="4" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="400" y="240" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EC6tnr1v8_Lx4r9o5bla-5" value="5" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="500" y="240" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EC6tnr1v8_Lx4r9o5bla-6" value="m种选择" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="90" y="300" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EC6tnr1v8_Lx4r9o5bla-7" value="m-1种选择,需要避让1号选择的宗教" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="180" y="300" width="80" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EC6tnr1v8_Lx4r9o5bla-9" value="m-1种选择,需要避让2号选择的宗教" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="290" y="300" width="80" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EC6tnr1v8_Lx4r9o5bla-10" value="m-1种选择,需要避让3号选择的宗教" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="390" y="300" width="80" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
1
TangDou/AcWing_TiGao/T5/QMI/1290.in
Normal file
1
TangDou/AcWing_TiGao/T5/QMI/1290.in
Normal file
@@ -0,0 +1 @@
|
||||
2 3
|
||||
82
TangDou/AcWing_TiGao/T5/QMI/1290.md
Normal file
82
TangDou/AcWing_TiGao/T5/QMI/1290.md
Normal file
@@ -0,0 +1,82 @@
|
||||
##[$AcWing$ $1290$. 越狱](https://www.acwing.com/problem/content/1292/)
|
||||
|
||||
### 一、题目描述
|
||||
监狱有连续编号为 $1$ 到 $n$ 的 $n$ 个房间,每个房间关押一个犯人。
|
||||
|
||||
有 $m$ 种宗教,每个犯人可能信仰其中一种。
|
||||
|
||||
如果相邻房间的犯人信仰的宗教相同,就可能发生越狱。
|
||||
|
||||
求有多少种状态可能发生越狱。
|
||||
|
||||
**输入格式**
|
||||
共一行,包含两个整数 $m$ 和 $n$。
|
||||
|
||||
**输出格式**
|
||||
可能越狱的状态数,对 $100003$ 取余。
|
||||
|
||||
**数据范围**
|
||||
$1≤m≤10^8$
|
||||
$1≤n≤10^{12}$
|
||||
|
||||
**输入样例**
|
||||
```cpp {.line-numbers}
|
||||
2 3
|
||||
```
|
||||
**输出样例**
|
||||
```cpp {.line-numbers}
|
||||
6
|
||||
```
|
||||
**样例解释**
|
||||
所有可能的 $6$ 种状态为:$(000)(001)(011)(100)(110)(111)$。
|
||||
|
||||
|
||||
### 二、解题思路
|
||||
本题可以采用容斥原理补集的思想。
|
||||
|
||||
考虑 $n$ 个犯人,$m$种宗教,如何安排不会导致犯罪。
|
||||
|
||||
第一个位置可以有 $m$ 个选择,则与第一个相邻的第二个位置就只有 $m−1$ 中选择。
|
||||
|
||||
考虑第 $i$ 个位置,则为了不和他左侧的 $i−1$ 位置发生冲突,一共有 $m-1$ 种选择。
|
||||
|
||||

|
||||
|
||||
因此不会导致犯罪的方案是: $m⋅(m−1)^{n−1}$
|
||||
|
||||
则会导致犯罪的方案是:$m^n−m⋅(m−1)^{n−1}$
|
||||
|
||||
计算一个数字的$n$次方,还要求取模,自然就需要使用快速幂~
|
||||
|
||||
<font color='red'><b>注意</b></font>
|
||||
注意减法取模可能会变成负数,那么我们要把他转化正数 $(a - b + mod) \% mod$ 即可
|
||||
|
||||
> 这里解释下:为什么取模+减法会出现负数呢?比如$MOD=10$
|
||||
> $a=13,b=5$
|
||||
> $ (a\%MOD -b \% MOD) \% MOD=13\%10 - 5 \%10=3-5=-2$
|
||||
> 出现负数不是我们想的结果,那就在取模时加上$MOD$就行了
|
||||
|
||||
### 三、实现代码
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define int long long
|
||||
const int MOD = 100003;
|
||||
|
||||
int qmi(int a, int b) {
|
||||
int res = 1;
|
||||
while (b) {
|
||||
if (b & 1) res = res * a % MOD;
|
||||
a = a * a % MOD;
|
||||
b >>= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
signed main() {
|
||||
int m, n;
|
||||
cin >> m >> n;
|
||||
cout << (qmi(m, n) - m * qmi(m - 1, n - 1) % MOD + MOD) % MOD << endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
18
TangDou/AcWing_TiGao/T5/QMI/TestQMI.cpp
Normal file
18
TangDou/AcWing_TiGao/T5/QMI/TestQMI.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define int long long
|
||||
|
||||
// 快速幂
|
||||
int qmi(int a, int b) {
|
||||
int res = 1;
|
||||
while (b) {
|
||||
cout << "b = " << (b & 1) << ", a = " << a << endl;
|
||||
if (b & 1) res = res * a;
|
||||
b >>= 1;
|
||||
a = a * a;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
signed main() {
|
||||
cout << qmi(2, 10) << endl;
|
||||
}
|
||||
98
TangDou/AcWing_TiGao/T5/QMI/快速幂、龟速乘总结.md
Normal file
98
TangDou/AcWing_TiGao/T5/QMI/快速幂、龟速乘总结.md
Normal file
@@ -0,0 +1,98 @@
|
||||
## 快速幂、龟速乘总结
|
||||
|
||||
### 一、快速幂
|
||||
|
||||
求 $a^b\ mod \ p$ 的结果。
|
||||
|
||||
**$Code$**
|
||||
```cpp {.line-numbers}
|
||||
// 快速幂(不加mod)
|
||||
int qmi(int a, int b) {
|
||||
int res = 1;
|
||||
while (b) {
|
||||
if (b & 1) res = res * a;
|
||||
b >>= 1;
|
||||
a = a * a;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 快速幂
|
||||
int qmi(int a, int b) {
|
||||
int res = 1;
|
||||
while (b) {
|
||||
if (b & 1) res = (res * a) % MOD;
|
||||
b >>= 1;
|
||||
a = a * a % MOD;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
```
|
||||
**解释一下**:
|
||||
|
||||
假如我们需要计算$2^{10}$,正常的办法是
|
||||
```cpp {.line-numbers}
|
||||
int s = 1;
|
||||
for (int i = 1; i <= 10; i++) s = s * 2;
|
||||
cout << s << endl;
|
||||
```
|
||||
毫无疑问,这个算法是正确的。但它执行的次数是$10$次,有没有什么办法可以优化一下运算次数呢?
|
||||
|
||||
**优化**
|
||||
|
||||
将$10$进行二进制分解$(10)_{10}=(1010)_2$
|
||||
这样处理后,从后向前,借助于我们熟悉的数位分离模板,就是遍历二进制的每一位。
|
||||
|
||||
此时,我们发现,最左面的数字$1$,权值是$8$,第三位的数字权值是$2$
|
||||
|
||||
同时,$2^8*2^2=2^{10}$
|
||||
|
||||
为什么会有这么神奇的现象呢?其实就是因为幂运算的性质造成:
|
||||
$$\large 2^{10}=2^{8+2}=2^8*2^2$$
|
||||
|
||||
$Q:$为啥非得拆成$8+2$,为啥不拆成$7+3$呢?
|
||||
就是因为类似于 **倍增** 的办法在计算中好处理呗!
|
||||
|
||||
$a$在代码中的使命就是:**我不管你用不用的上,反正我每次是翻倍!**
|
||||
而枚举$b$的每一个数位,就是看看这个位置上的当前$a$是不是需要乘进来!幂运算的性质成功的把幂与二进制加法结合起来了。
|
||||
|
||||
把倍增的思路$2,4,8,16,32,...$这样长上来的,这是因为
|
||||
$2^1*2^1=2^2$
|
||||
$2^2*2^2=2^4$
|
||||
$2^4*2^4=2^8$
|
||||
$2^8*2^8=2^{16}$
|
||||
$2^{16}*2^{16}=2^{32}$
|
||||
|
||||
**模板题** : **[$P1226$ 【模板】快速幂||取余运算](https://www.luogu.com.cn/problem/P1226)**
|
||||
|
||||
|
||||
|
||||
### 二、龟速乘
|
||||
求 $a*b\ mod \ p$ 的结果,$a,b,p$ 都是 $10^{18}$ 级别。
|
||||
|
||||
$Code$
|
||||
```cpp {.line-numbers}
|
||||
// 龟速乘,快速加
|
||||
int qadd(int a, int b) {
|
||||
int res = 0;
|
||||
while (b) {
|
||||
if (b & 1) res = (res + a) % MOD;
|
||||
b >>= 1;
|
||||
a = (a + a) % MOD;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
```
|
||||
|
||||
这东西怎么理解呢?
|
||||
|
||||
**举栗子吧**:
|
||||
|
||||
$5*6_{10}=5*(110)_2$
|
||||
|
||||
最右侧的$0$对就的权值是$5^1=5$ ①
|
||||
右侧第二的$1$对就的权值是$5*2=10$ ②
|
||||
右侧第三的$1$对就的权值是$10*2=20$ ③
|
||||
|
||||
而$② ③$对应的位置上有数字$1$,有效,$①$无效
|
||||
结果就是$10+20=30$
|
||||
Reference in New Issue
Block a user