高效素数打表——欧拉打表
s[i+1].find(s[i])==s[i+1].npos// npos 表示不存在
#include<iostream>
#define maxn 100000
#define maxl 1000000
using namespace std;
int prime[maxn];
bool vis[maxl];
void get_prime(){//线性时间筛法——欧拉筛法
int cnt=0;
int i,j;
for(i=2;i<maxl;i++){
if(!vis[i]){
prime[cnt++]=i;vis[i]=true;
}
for(j=0;j<cnt;j++){
if(i*prime[j]>maxl)break;
vis[i*prime[j]] =true;
if(i%prime[j]==0) break;
}
}
}
int main(){
get_prime();
for(int i=0;i<100;i++) cout<<prime[i]<<endl;
return 0;
}
最长对称子序列——偶数,奇数
#include<iostream>
#include<algorithm>
#include<set>
#include<cstring>
using namespace std;
int main() {
string a;
while (getline(cin, a)) {
int l = a.length();
int len = 0;
for (int i = 0; i < l; i++) {
for (int j = 0; i - j >= 0 && i + j < l; j++) {
if (a[i - j] != a[i + j]) break;
if (2 * j + 1 > len) len = 2 * j + 1;
}
for (int j = 0; i - j >= 0 && i + j <= l; j++) {
if (a[i - j] != a[i + j + 1]) break;
if (2 * j + 2 > len) len = 2 * j + 2;
}
}
cout << len << endl;
} return 0;
}
最长子序列
#include<iostream>
using namespace std;
int maxs(const int a[], int n) {
int thissum, maxsum, j;
thissum = maxsum = 0 ;
for (j = 0; j < n; j++) {
thissum += a[j];
if (thissum > maxsum) maxsum = thissum;
else if (thissum < 0) thissum = 0;
}
return maxsum;
}
int main() {
int a[1000];
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
int maxss=maxs(a, n);
cout << maxss << endl;
system("pause");
return 0;
}
kmp 算法 ——两个字符串 匹配 输出 起始 index
#include<iostream>
using namespace std;
const int maxl = 1000000;
const int maxn = 100000;
int a[maxl], b[maxn];
int n, m, f;//m 模板长度 n 匹配串长度
int nex[maxn];
void get_next() {
int i = 0; int j = -1;
nex[0] = -1;
while (j < n) {
if (j == -1 || a[i] == b[j])nex[++i] = ++j;
else j = nex[j];
}
}
void kmp() {
int i =0, j =0;
get_next();
while (i < m) {
if (j == -1 || a[i] == b[j])
{
i++; j++;
}
else j = nex[j];
if (j == n) {
cout << i - n + 1 << endl;
f = 0;
break;
}
}
}
int main(){
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
f = 1;
for (int i = 0; i < m; i++) cin >> a[i];
for (int i = 0; i < n; i++) cin >> b[i];
kmp();
if (f) cout << "-1" << endl;
}return 0;
}
欧几里得算法————求两个数的最大公因数
unsigned int gcd(int x, int y) {//循环实现
unsigned int rem;
while (y > 0) {
rem = x % y;
x = y;
y = rem;
}
return x;
}
int gcd1(int x, int y) {//递归实现
return y == 0 ? x : gcd(y, x%y);
}
最小公倍数 ——借助gcd()
int g(int x, int y) {
return x / gcd(x, y)*y;
}// 先除法后乘法 防止数据溢出
对分查找————排好序的数组中查找某一元素T
int BinarySearch(const ElementType a[],ElwmentTpye T,int n){
int low,mid,high;
low=0;
high=n-1;
while(low<=high){
mid=(low+high)/2;
if(a[mid]<x){
low=mid+1;
}else if(a[mid]>x){
high=mid-1;
}else return mid;/* found*/
}
return -1;/*notfound*/
}
快速幂
long int pow(long int x,long int n){
if(n==0) return 1;
if(n==1) return x;
if(n%2){//奇数个
return pow(x*x,n/2)*x;
}else return pow(x*x,n/2);//偶数个
}
两点间的最短路径——固定一点到其余所有点的最短路径(Dijkstra算法)(没有负边的情况)
#include<iostream>
#include<sstream>
using namespace std;
#define M 210
#define INF 0x3f3f3f
int arr[M][M], vis[M], dis[1010];// arr 路径 // vis 标记数组 dis 距离
int n, m;
void Dijkstra(int src) {//一点(src) 到 其余所有点的最短路径
for (int i = 0; i < n; i++) {
vis[i] = 0; dis[i] = arr[src][i];
}
int temp, k;
vis[src] = 1; dis[src] = 0;
for (int i = 0; i < n; i++) {
temp = INF;
for (int j = 0; j < n; j++) {
if (!vis[j] && temp > dis[j]) {
temp = dis[j];
k = j;
}
}
vis[k] = 1;
for (int j = 0; j < n; j++) {
if (!vis[j] && dis[j] > arr[k][j] + dis[k]) dis[j] = arr[k][j] + dis[k];
}
}
}
void work() {
int s, t, u, v, w;
while (cin>>n>>m) {
for (int i = 0; i < n; i++) for(int j=0;j<n;j++) arr[i][j] = INF;//初始化
for (int i = 0; i < m; i++) {
cin >> u >> v >> w;
if(arr[u][v]>w) arr[u][v] = arr[v][u] = w;//输入 ——输入最短路径 (可能路不只有一条)
}
cin >> s >> t;// 需要 求得 s 到 t(也可以是其他值) 的最短路径
Dijkstra(s);//
if (dis[t] != INF) cout<< dis[t]; else cout << "-1";
puts("");
}
}
int main() {
work();
system("pause");
return 0;
}
//Dijkstra 算法的另一种写法
#include<iostream>
#include<cmath>
#include<math.h>
#include<sstream>
#include<cstring>
using namespace std;
#define M 110
#define INF 0x3f3f3f
int arr[M][M], vis[M], dis[1010];//三个数组都需要初始化
/*
arr数组 初始化 目的: 保证在输入的 两地之间 只记录最短的距离 (可能两地有不止一条路)
vis 标记是否被读取 走过的路不再重复
dis 初始为最远
*/
int n, m;// n 顶点数
int min(int x, int y) {
return x < y ? x : y;
}
void Dijkstra(int src) {//一点 到 其余所有点的最短路径
memset(vis, 0, sizeof(vis));
memset(dis, INF, sizeof(dis));
dis[src] = 0;
while (true) {
int v = -1;
//从尚未选择的顶点中选一个距离最小的点
for (int i = 1; i <= n; i++) {
if (!vis[i] && (v ==-1 || dis[i] < dis[v])) v = i;
}
if (v == -1) break;
vis[v] = 1;
for (int i = 1; i <= n; i++) {
dis[i] = min(dis[i],dis[v] + arr[v][i]);
}
}
}
void work() {
int s, t, u, v, w;
while (cin>>n>>m) {
if (m == 0 && n == 0) break;
for (int i = 1; i <= n; i++) for(int j=1;j<=n;j++) arr[i][j] = INF;
for (int i = 0; i < m; i++) {
cin >> u >> v >> w;
if(arr[u][v]>w) arr[u][v] = arr[v][u] = w;
}
s = 1; t = n;
Dijkstra(s);
cout << dis[t];
puts("");
}
}
int main() {
work();
system("pause");
return 0;
}
最小生成树——用于求取一棵树上最近的联通距离(eg: 连接所有村庄的电线最短长度)
#include <iostream>
#include<math.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 101;
int n; //节点数
int mp[N][N];//地图
int dis[N];//存储距离
int vis[N];//标记
int min(int x, int y) {
return x < y ? x : y;
}
int prime(int s) //传进起始点
{
for (int i = 0; i < n; i++) {
dis[i] = inf;
vis[i] = 0;
}
dis[s] = 0;
int res = 0;
while (true) {
int v = -1;
for (int i = 0; i < n; i++) if (!vis[i] && (v == -1 || dis[i] < dis[v])) v = i;;
if (v == -1) break;
vis[v] = true;
res += dis[v];
for (int i = 0; i < n; i++) {
dis[i] = min(dis[i], mp[v][i]);
}
}return res;
}
void work() {
while (cin >> n) {
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) { cin >> mp[i][j]; if (!mp[i][j]) mp[i][j] = inf; }
int num = prime(0);
cout << num << endl;
}
}
int main() {
work();
system("pause");
return 0;
}
//法二
void prim(){
int i,j,d[MAXV],vis[MAXV],mi,v;
for(i=1;i<=n;i++){
d[i]=map[1][i];
vis[i]=0;
}
for(i=1;i<=n;i++){
mi=inf;
for(j=1;j<=n;j++)
if(!vis[j] && d[j]<mi){
mi=d[j];
v=j;
}
vis[v]=1;
for(j=1;j<=n;j++)
if(!vis[j] && d[j]>map[v][j])
d[j]=map[v][j];
}
for(d[0]=0,i=1;i<=n;i++) d[0]+=d[i];
printf("%d\n",d[0]);
}
// 法三
const int inf = 0x3f3f3f3f;
const int N = 30;
int n; //节点数
int mp[N][N];//地图
int dis[N];//存储距离
int vis[N];//标记
int prime(int s) //传进起始点
{
int sum = 0; //权值总和
for(int i = 0;i < n;i ++) //初始化起始点到各点的距离
dis[i] = mp[s][i];
vis[s] = 1;
for(int i = 1;i <= n - 1;i ++)
{
// n - 1次迭代
int minn = inf;
int p;
for(int j = 0;j < n;j ++) //找到距离最小的点
{
if(!vis[j] && dis[j] < minn)
minn = dis[j], p = j;
}
vis[p] = 1;
sum += minn; //加上边权值
for(int j = 0;j < n;j ++) //松弛操作
{
if(!vis[j] && dis[j] > mp[p][j])
dis[j] = mp[p][j];
}
}
return sum;
}
memset 的使用
#include<cstring>
//memset赋值时以 单字节赋值
//memset使用时要千万小心,在给char以外的数组赋值时,只能初始化为0或者-1。
char a[10];
int num[10];
memset(a,'A',sizeof(a));//是可以的 效果是全部复制为‘A’
memset(num,0,sizeof(num));//也可以
memset(num,1,sizeof(num));//不可以