#本人代码习惯
第一次写博客简单说一下个人的代码习惯以及介绍一些小东西
#include <bits/stdc++.h>
using namespace std;
万能头文件大多数OJ和比赛环境都支持这个头文件 相当于一次性引用了所有头文件
C++标准库中 基本所有函数都需要在前面带上std:: 可以直接使用using namespace std;启用std命名空间就不用再打std::了
#include <stdio.h>
在题目有大量数据输入输出时C++的接受速度会比C标准库中的慢很多(cstdio中的scanf也比stdio.h中的慢) 所以习惯性就第一行带上stdio.h的头文件
const int INF = 0x3f3f3f3f;
竞赛常用int最大值
好处memset(arr, 0x3f, sizeof(arr));可以直接将整个数组初始化为这个值
还有这个值相加不爆int相乘不爆long long
const int MAXN = 1e2 + 10;
定义MAXN方便整体调整数组大小 开头定义后面统一使用注意要加const才可以
#ifdef LOCAL
#endif
其中#ifdef LOCAL与#endif是预编译宏
当定义了#define LOCAL或在编译器中附加指令(拿DevC++5.4.0举例子在工具选项中加入-DLOCAL)
只有这样#ifdef LOCAL与#endif之间的代码才会在编译后生效
用处就是可以在中间加上调试指令 提交到OJ的时候并不会生效而影响最终答案

freopen("C:/input.txt", "r", stdin);
重定向输入流 从文件读入数据
在做题需要调试的时候 如果题目数据量比较大每次都输入过于麻烦 可以使用这条指令让程序从文件读入(C:/input.txt文件也可以是相对路径)
#C题 矩阵乘法 <模拟>
按照数学的矩阵乘法规则进行模拟(详见矩阵乘法_百度百科)
附上AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e2 + 10;
int g1[MAXN][MAXN], g2[MAXN][MAXN], g[MAXN][MAXN];
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int n;
cin >> n;
for (int i = 0; i < n; i++) //接受矩阵1存为g1
for (int j = 0; j < n; j++)
scanf("%d", &g1[i][j]);
for (int i = 0; i < n; i++) //接受矩阵2存为g2
for (int j = 0; j < n; j++)
scanf("%d", &g2[i][j]);
for (int i = 0; i < n; i++) //矩阵相加存为g
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
g[i][j] += g1[i][k] * g2[k][j];
for (int i = 0; i < n; i++) //输出g
{
for (int j = 0; j < n; j++)
{
if (j)
putchar(' '); //注意行尾不能多空格
printf("%d", g[i][j]);
}
putchar('\n'); //每行有换行符
}
return 0;
}
#D题 WERTYU <字符串>
题目字符种类和字符串总长度都很小 直接暴力做法
先建立一个字符串列表mp每个字符都进行查找然后输出其前一位的字符
采用修改接收到的字符数组再输出的方法也行 注意多样例之间要输出换行否则会答案错误
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
char mp[] = "`1234567890-=QWERTYUIOP[]\ASDFGHJKL;'ZXCVBNM,./"; //滚键盘写的字符列表
char c;
while (scanf("%c", &c) != EOF) //我采用每次接受一个字符然后输出
{
int flag = 1;
for (int i = 0; mp[i] != 0; i++)
{
if (mp[i] == c)
{
printf("%c", mp[i - 1]);
flag = 0;
break;
}
}
if (flag) //如果接收到的不是字符列表中的字符则直接输出 如果输出过了就不会再输出了(换行符)
printf("%c", c);
}
return 0;
}
#M题 A^B Mod C <数论> <快速幂>
数论的快速幂算法 题目给出A,B,C都是在1e9范围内的 如果采用朴素算法一次一次往上乘会超时
快速幂算法的思想 a^11 = a^8 * a^2 * a^1将次方转化为二进制的和然后用一个变量代表着a的二进制次方每次进行平方对应B次方的二进制位乘入答案中并且取模
百度百科_快速幂
为什么数据要取模
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int main()
{
#ifdef LOCAL
//freopen("C:/input.txt", "r", stdin);
#endif
long long a, b, c, ans = 1; //直接定义为long long后面不用担心相乘的时候还没取模就爆了int
cin >> a >> b >> c;
while (b) //b为次方数量 此处的意思为b为0的时候不在进行循环
{
if (b & 1) //如果b的二进制位末尾为1则将a的对应次方乘入最终答案 详见百度百科~
ans = (ans * a) % c; //乘完了记得取模
a = (a * a) % c, b >>= 1; //a自身平方 相当于a^4->a^8或a^8->a^16等 b >>= 1为C++中的位运算操作 相比/2会更快
}
cout << ans << endl;
return 0;
}
#X题 斐波那契数列的第N项 <数论> <矩阵快速幂>
前面的矩阵乘法和快速幂就是为这题铺垫的
矩阵快速幂 利用矩阵乘法得到递推式的某一项 矩阵的乘法过程中利用快速幂加快计算
假设A矩阵为
[
F
[
i
−
1
]
F
[
i
]
]
\left[ \begin{matrix} F[i - 1] & F[i] \end{matrix} \right]
[F[i−1]F[i]]
B矩阵为
[
0
1
1
1
]
\left[ \begin{matrix} 0 & 1\\ 1 & 1 \end{matrix} \right]
[0111]
A矩阵乘上B矩阵之后就会得到
[
F
[
i
]
F
[
i
−
1
]
+
F
[
i
]
]
\left[ \begin{matrix} F[i] & F[i - 1] + F[i] \end{matrix} \right]
[F[i]F[i−1]+F[i]]
根据公式F(n) = F(n - 1) + F(n - 2)得
[
F
[
i
]
F
[
i
+
1
]
]
\left[ \begin{matrix} F[i] & F[i + 1] \end{matrix} \right]
[F[i]F[i+1]]
等于A矩阵的两项都往后移了一项 乘的这个B矩阵是F(n) = F(n - 1) + F(n - 2)递推式的转移矩阵
如果A矩阵为
[
F
[
0
]
F
[
1
]
]
\left[ \begin{matrix} F[0] & F[1] \end{matrix} \right]
[F[0]F[1]]
乘上转移矩阵的n-1次方后就会转化为
[
F
[
n
]
F
[
n
+
1
]
]
\left[ \begin{matrix} F[n] & F[n + 1] \end{matrix} \right]
[F[n]F[n+1]]
这个矩阵的 左边的一项则为所求 下面的代码中省去了A矩阵 直接求B矩阵的n-1次方
其中的u最开始的状态为单位矩阵 相当于在快速幂中最开始的ans = 1 任何矩阵乘上单位矩阵都等于原矩阵
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 9;
const int MAXN = 2; //强迫症 就算是2我也要写MAXN
void matrix(long long a[MAXN][MAXN], const long long b[MAXN][MAXN]) //矩阵乘法函数 将ab矩阵相乘然后保存回a矩阵
{
long long t[MAXN][MAXN]; //定义一个矩阵用来保存相乘的结果2*2的二位可以开在全局变量中 太大会崩溃
memset(t, 0, sizeof(t));
for (int i = 0; i < MAXN; i++)
for (int j = 0; j < MAXN; j++)
for (int k = 0; k < MAXN; k++)
t[i][j] = (t[i][j] + a[i][k] * b[k][j]) % MOD; //矩阵相乘
for (int i = 0; i < MAXN; i++)
for (int j = 0; j < MAXN; j++)
a[i][j] = t[i][j]; //覆盖存入a中
}
int main()
{
#ifdef LOCAL
//freopen("C:/input.txt", "r", stdin);
#endif
long long n;
cin >> n;
if (n == 0) //0和1的时候直接特判进行输出
cout << 0 << endl;
if (n == 1)
cout << 1 << endl;
long long t[MAXN][MAXN] = { 1, 1, 1, 0 }, u[MAXN][MAXN] = { 1, 0, 0, 1 }; //转移矩阵t 单位矩阵u
n -= 1; //这里n不减少一次会多计算一项
while (n) //矩阵快速幂 将矩阵的n次方转换为快速幂的形式
{
if (n & 1)
matrix(u, t);
matrix(t, t);
n >>= 1;
}
cout << u[0][0] << endl; //输出u[0][0]即为第n项的答案
return 0;
}
本文分享了作者的C++编程习惯,介绍了万能头文件、预编译宏的使用,并通过具体题目详解了矩阵乘法、快速幂及矩阵快速幂算法的应用。
1241

被折叠的 条评论
为什么被折叠?



