容易忘记的操作
擦除空格
str.erase(remove(str.begin(), str.end(), ' '), str.end());
向上取整
printf("%.0f\n", ceil(a));
向下取整
printf("%.0f\n", floor(a));
算法
初始化素数数组
先将数组初始化为true,然后从i开始每次的倍数改成false,记得i 的平方不能大于最大int 的最大表示范围,即65536。在用另外一个int数组来记录当前的素数。
void init() {
for (int i = 0; i < N; i++) isPrime[i] = true;
for (int i = 2; i < N; i++) {
if (!isPrime[i]) continue;
if (primepos > 10000) break;
Prime[++primepos] = i;
if (i >= 65536) continue;
for (int j = i*i; j >= 0 && j < N; j+=i) {
isPrime[j] = false;
}
}
}
质因数分解
先初始化质数数组,再通过for循环统计
int factorization(int num, int factors[]) {
int pos = 0;
int len = sqrt(num);
for (int i = 2; i <= len; i++) {
while (num != 0 && num % i == 0) {
factors[pos++] = i;
num /= i;
}
}
if (num > 1) factors[pos++] = num;
return pos;
}
最大公约数
int gcd(int num1, int num2) {
if (num2 == 0) return num1;
return gcd(num2, num1%num2);
}
最小公倍数
int lcm(int num1, int num2) {
int factor = gcd(num1, num2);
return num1/factor*num2; // 考虑到溢出的可能性,先除后乘
}
kmp算法
重点是next数组的建立,next数组是针对pattern的,初始化为-1,相同则等于 next[i] = k,不同则等于k = next[k]。其次重点是循环遍历的时候,注意将不同的时候,j = next[j]+1,因为在i的for循环中i已经自动+1了。
void get_next(int* next, char* p, int n) {
next[0] = -1;
int k = -1, j = 0;
while (j < n) {
if (k == -1 || p[j] == p[k]) {
k++;
j++;
next[j] = k;
} else {
k = next[k];
}
}
}
for (i = 0; i < n; i++) {
if (t[i] == p[j]) j++;
else j = next[j]+1;
if (j == m) {
count++;
j = next[j];
}
}
第k大的数
找第k大的数,利用快排的思想(swap可以用algorithm里面的)
int find(vector<int>& nums, int first, int last, int k) {
if (first > last) return -1;
else if (first == last) return nums[first];
int key = nums[first];
for (int i = last; i > first; i--) {
if (nums[i] >= key) {
swap(nums, last, i);
last--;
}
}
swap(nums[first], nums[last]);
if (k == nums.size()-last) return nums[last];
else if (k > nums.size()-last) return find(nums, first, last-1, k);
else return find(nums, last+1, nums.size()-1, k);
}
数学表达式的计算
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <algorithm>
#include <cctype>
using namespace std;
double calculate(string str);
double parseNum(string str, int& i);
double parseExpr(string str, int& i);
int main() {
string str;
cin >> str;
double res = calculate(str);
printf("%0.0f\n", res);
return 0;
}
double calculate(string str) {
cout << str << endl;
str.erase(remove(str.begin(), str.end(), ' '), str.end());
int i = 0;
cout << str << endl;
double res = parseExpr(str, i);
return res;
}
double parseExpr(string str, int& i) {
stack<double> sta;
char op = '+';
double tmp = 0;
for (; i < str.size() && str[i] != ')'; i++) {
double num = 0;
if (str[i] == '(') tmp = parseExpr(str, i);
else tmp = parseNum(str, i);
switch(op) {
case '-':
sta.push(-tmp);
break;
case '+':
sta.push(tmp);
break;
case '*':
num = sta.top() * tmp;
sta.pop();
sta.push(num);
break;
case '/':
num = sta.top() / tmp;
sta.pop();
sta.push(num);
break;
}
op = str[i];
tmp = 0;
}
double res = 0;
while (!sta.empty()) {
res += sta.top();
sta.pop();
}
return res;
}
double parseNum(string str, int& i) {
double res = 0;
for (; i< str.size(); i++) {
if (isdigit(str[i])) res = res*10 + str[i] - '0';
}
return res;
}
排列组合
关键点:j -> i,
void init() {
Cmn[0][1] = Cmn[1][1] = 1;
for (int i = 1; i < 21; i++) {
Cmn[0][i] = 1;
for(int j=1;j<=i;j++)
if(i==j) Cmn[j][i]=1;
else Cmn[j][i]=Cmn[j-1][i-1]+Cmn[j][i-1]; //
}
return;
}
附:
bool isdigit(char c);
在<iostream>
已经定义了- 注意看清楚样例的输出格式,特别是没有oj系统时。
- 注意调试cout出来的数记得注释掉
- 递归返回条件顺序容易错,判断先返回还是先处理再返回。见combination-sum-ii/