高效素數打表——歐拉打表
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;
}