常見資料結構/演算法模板
title: 常見資料結構/演算法模板
date: 2020-08-20
categories: acm
tags: acm
top: true
0. to start with
remembering one trick is better than recording a hundred.
包含一些模板和例題
技巧,STL,函式,細節,參考資料(比如揹包九講)等見 https://www.cnblogs.com/lqerio/p/13484897.html
1. DP Dynamic Programming
如果前面的結果可以被利用,就可以dp。
先寫狀態轉移方程,邊界條件,初始結束狀態的設定。
如果資料計算量大可以預處理。
woj1023.
dp 狀態轉移方程: f[i]=min(f[i],f[j]+valuecluser[j+1][i])(i-j>=p) //j+1...注意分界點 dp[0]=0.i in range p-1-N (編號為1-n)
//dp注意初始狀態結束狀態預處理。f[0]=0,f[i]初始為maxd
預處理:計算valuecluster[i][j]
1.1 Pack 揹包
1.1.1 01揹包
WOJ1005 const int maxn=10005; int value[maxn]; int sizee[maxn]; int final[100005]; for(int i=0;i<=noah;i++) final[i]=0; for(int i=0;i<n;i++) for(int j=noah;j>0;j--) //倒序理解就是01揹包只有一件,前i-1件已經判斷完了,只判斷這一件,在比較小的情況下放不影響在比較大的情況放 if(j>=sizee[i]) //final可行因為如果小的能放大的也能放。 final[j]=max(final[j],final[j-sizee[i]]+value[i]); cout<<final[noah]<<endl; }
1.2 剪枝 / 回溯
還是待更新!!!!
下面的不全
剪枝
1.最優化剪枝:如果當前已經找到的最優路徑長度為L ,那麼在繼續搜尋的過程中,總長度已經大於等於L的走法,就可以直接放棄,不用走到底了
2.可行性剪枝:如果當前到達城市的路費已大於k,或者等於k且沒有到達終點,就可以直接放棄。
回溯
used[i] = 1;//設為用過
dfs(u + 1);//下一個數字
used[i] = 0;//回溯:回到沒用過
1.3 方格&&滾動陣列&&優化時間
見我的woj1012題解
2. DFS
2.1 recursive
PAT 1004
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
vector<int>nodes[100];
int ans[105];
int level;
void dfs(int id,int depth){
level=max(level,depth);
int temp=id;
if(nodes[temp].size()==0){
ans[depth]++;
}
else{
for(int i=0;i<nodes[temp].size();i++){
dfs(nodes[temp][i],depth+1);
}
}
}
int main(){
int n,m;
cin>>n>>m;
int father,num,son;
for(int i=0;i<m;i++){
cin>>father>>num;
for(int j=0;j<num;j++){
cin>>son;
nodes[father].push_back(son); // at first i write push_back[]
}
}
level=1;
dfs(1,level);
cout<<ans[1];
for(int i=2;i<=level;i++) //at first i write push_back[] < but not <=
cout<<' '<<ans[i];
system("pause");
return 0;
}
2.2 stack
找到與最先出發點的所有鄰接點,將他們入棧,
標記這些點已經訪問過,後面和bfs的佇列實現有點像。
UVA280
#include<bits/stdc++.h>
using namespace std;
const int maxn=150;
int node_num,st,ed,stnodenum,stnode,vis[maxn];
void dfs(int stnode,vector<int> v[]){
memset(vis,0,sizeof(vis));
stack<int> s;
vector<int> t;
for(int i=0;i<v[stnode].size();i++){
int temp=v[stnode][i];
if(!vis[temp]){
s.push(temp);
vis[temp]=1;
}
}
while(!s.empty()){
int ans=s.top();
s.pop();
for(int i=0;i<v[ans].size();i++){
int temp=v[ans][i];
if(!vis[temp]){
s.push(temp);
vis[temp]=1;
}
}
}
for(int i=1;i<=node_num;i++){
if(!vis[i])
t.push_back(i);
}
cout<<t.size();
for(int i=0;i<t.size();i++)
cout<<" "<<t[i];
cout<<endl;
}
int main(){
while(scanf("%d",&node_num)!=EOF){
if(node_num==0) break;
vector<int> v[maxn];
for(;;){
scanf("%d",&st);
if(!st)
break;
for(;;){
scanf("%d",&ed);
if(!ed)
break;
v[st].push_back(ed);
}
}
scanf("%d",&stnodenum);
for(int i=0;i<stnodenum;i++){
scanf("%d",&stnode);
dfs(stnode,v);
}
}
return 0;
3. BFS
3.1 QUEUE
PAT 1004
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
vector<int>nodes[100];
int ans[105];
int depth[105];
int level;
void bfs(int id){
queue<int>q;
q.push(id);
while(!q.empty()){
int temp=q.front(); //at first i write "top()"
q.pop();
level=max(level,depth[temp]);
if(nodes[temp].size()==0){
ans[depth[temp]]++;
}
else{
for(int i=0;i<nodes[temp].size();i++){
depth[nodes[temp][i]]=depth[temp]+1;
q.push(nodes[temp][i]);
}
}
}
}
int main(){
int n,m;
cin>>n>>m;
int father,num,son;
for(int i=0;i<m;i++){
cin>>father>>num;
for(int j=0;j<num;j++){
cin>>son;
nodes[father].push_back(son); // at first i write push_back[]
}
}
depth[1]=1;
level=1;
bfs(1);
cout<<ans[1];
for(int i=2;i<=level;i++) //at first i write push_back[] < but not <=
cout<<' '<<ans[i];
system("pause");
return 0;
}
3.2 recursion
void BFS(int st) {
int len = G[st].size();
for (int i = 0 ; i < len ; i ++ ) {
que.push(G[st][i]);
}
if ( !que.empty() ) {
int top = que.front() ; que.pop() ;
printf("%d ",top) ;
BFS(top) ;
}
4. topo 拓撲排序
//拓撲排序可以判斷有向圖有沒有環。
//dfs判斷圖聯通。
5. math
5.1 euler path /circuit
https://www.cnblogs.com/wkfvawl/p/9626163.html
DFS Fleury(佛羅萊)演算法求解
5.2 Huffman Coding 哈夫曼編碼
6. GRAPH 圖
6.1 Red Black Tree
6.2 AVL
6.3 tree traversal 樹的遍歷
https://www.cnblogs.com/qjmnong/p/9135386.html
Pre-order
recursive
void pre_order(TreeNode * Node)
{
if(Node == NULL)
return;
printf("%d ", Node->data);
pre_order(Node->left);
pre_order(Node->right);
}
Iteration
class TreeNode {
public int val;
public TreeNode left, right;
public TreeNode(int val) {
this.val = val;
this.left = this.right = null;
}
}
先push(root)
node = pop()
loop:
list.add( node.val )
push( node.right )
push( node.left )
迴圈步驟直到棧空
public List<Integer> preorderTraversal(TreeNode root) {
if (root == null) {
return null;
}
List<Integer> list = new ArrayList<Integer>();
Stack<TreeNode> s = new Stack<TreeNode>();
s.push(root);
while (!s.isEmpty()) {
TreeNode node = s.pop();
list.add(node.val);
if (node.right != null) {
s.push(node.right);
}
if (node.left != null) {
s.push(node.left);
}
}
return list;
}
Middle-order
recursive
void middle_order(TreeNode *Node)//中序遍歷遞迴演算法
{
if(Node == NULL)
return;
middle_order(Node->left);
printf("%d ", Node->data);//在中間
middle_order(Node->right);
}
Iteration
把root、以及root左孩子都壓入棧中
loop:
node = pop()
list.add( node.val )
root = node.right
迴圈步驟直到棧為空且root為null
public static List<Integer> inorderTraversal(TreeNode root) {
if (root == null) {
return null;
}
List<Integer> list = new ArrayList<Integer>();
Stack<TreeNode> s = new Stack<TreeNode>();
do {
while (root != null) {
s.push(root);
root = root.left;
}
if (!s.isEmpty()) {
TreeNode node = s.pop();
list.add(node.val);
root = node.right;
}
} while (!s.isEmpty() || root != null);
return list;
}
Post-order
recursive
void post_order(TreeNode *Node)//後序遍歷遞迴演算法
{
if(Node == NULL)
return;
post_order(Node->left);
post_order(Node->right);
printf("%d ", Node->data);//在最後
}
Iteration
先push(root)
loop:
node = pop()
list.add( 0 , node.val )
push( node.left )
push( node.right )
迴圈步驟3直到棧空
之後倒序遍歷list
public static List<Integer> postorderTraversal(TreeNode root) {
if (root == null) {
return null;
}
List<Integer> list = new ArrayList<Integer>();
Stack<TreeNode> s = new Stack<TreeNode>();
s.push(root);
while( !s.isEmpty() ) {
TreeNode node = s.pop();
if(node.left != null) {
s.push(node.left);
}
if(node.right != null) {
s.push(node.right);
}
list.add(0, node.val);
}
return list;
}
6.4 BST (binary search tree)
https://www.cnblogs.com/lqerio/p/11901828.html
6.5 最短路
https://blog.csdn.net/strve/article/details/80957491
Floyed +Dijkstra + Bellman-Ford + SPFA (SPFA就是佇列優化版的BF)。
///BF 適用於含有負邊的圖。如果有負邊,返回false。Dijkstra演算法無法判斷含負權邊的圖的最短路.二者都適用於有向有環圖。
//拓撲排序可以判斷有向圖有沒有環。
//dfs判斷圖聯通。
6.5.1 dijkstra
PAT 1003 為例
模板 Dijkstra+鏈式前向星+堆優化
https://www.cnblogs.com/zmin/p/7349100.html
matrix O() 鄰接矩陣版
#include<bits/stdc++.h>
using namespace std;
int graph[505][505];//圖
int city[505],dis[505],pathNum[505],teamNum[505];//每個城市救護隊的數量、到達每個城市的最短距離、到達每個城市的最短路徑的數量、到達每個城市的救護隊數量
bool visit[505];//每個城市是否被訪問過
int N,M,C1,C2;
void Dijkstra(){
while(!visit[C2]){//如果終點城市還沒有被訪問,繼續迴圈
int MIN=INT_MAX,v=-1;//找出目前距離最短的還沒有被訪問的城市
for(int i=0;i<N;++i)
if(!visit[i]&&MIN>dis[i]){
MIN=dis[i];
v=i;
}
visit[v]=true;//標記為已訪問
for(int i=0;i<N;++i)
if(!visit[i]&&graph[v][i]!=0&&dis[v]+graph[v][i]<dis[i]){
dis[i]=dis[v]+graph[v][i];//更新最短路徑長度
pathNum[i]=pathNum[v];//更新最短路徑數量
teamNum[i]=teamNum[v]+city[i];//更新城市的救護隊數量
}else if(graph[v][i]!=0&&dis[v]+graph[v][i]==dis[i]){
pathNum[i]+=pathNum[v];//增加最短路徑數量
teamNum[i]=max(teamNum[i],teamNum[v]+city[i]);//找出能夠召集最多的城市救護隊數量
}
}
}
int main(){
scanf("%d%d%d%d",&N,&M,&C1,&C2);
for(int i=0;i<N;++i)
scanf("%d",&city[i]);
while(M--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
graph[a][b]=c;
graph[b][a]=c;
}
fill(dis,dis+N,INT_MAX);//將最短路徑均設定為最大值
dis[C1]=0;//C1城市是起點,最短路徑為0
teamNum[C1]=city[C1];//C1城市是起點,最短路徑數量為1
pathNum[C1]=1;//C1城市是起點,能夠召集的救護隊數量為本城市的數量
Dijkstra();
printf("%d %d",pathNum[C2],teamNum[C2]);//輸出
return 0;
}
鄰接表版
#include<bits/stdc++.h>
using namespace std;
struct Road{
int v;//道路盡頭的城市編號
int length;//道路長度
Road(int vv=0,int l=0):v(vv),length(l){}
};
vector<vector<Road>>graph(505);//圖
int city[505],dis[505],pathNum[505],teamNum[505];//每個城市救護隊的數量、到達每個城市的最短距離、到達每個城市的最短路徑的數量、到達每個城市的救護隊數量
bool visit[505];//每個城市是否被訪問過
int N,M,C1,C2;
void Dijkstra(){
while(!visit[C2]){//如果終點城市還沒有被訪問,繼續迴圈
int MIN=INT_MAX,v=-1;//找出目前距離最短的還沒有被訪問的城市
for(int i=0;i<N;++i)
if(!visit[i]&&dis[i]<MIN){
MIN=dis[i];
v=i;
}
visit[v]=true;//標記為已訪問
for(Road r:graph[v]){
if(!visit[r.v]&&dis[r.v]>dis[v]+r.length){
dis[r.v]=dis[v]+r.length;//更新最短路徑長度
pathNum[r.v]=pathNum[v];//更新最短路徑數量
teamNum[r.v]=teamNum[v]+city[r.v];//更新城市的救護隊數量
}else if(dis[r.v]==dis[v]+r.length){
pathNum[r.v]+=pathNum[v];//增加最短路徑數量
teamNum[r.v]=max(teamNum[r.v],teamNum[v]+city[r.v]);//找出能夠召集最多的城市救護隊數量
}
}
}
}
int main(){
scanf("%d%d%d%d",&N,&M,&C1,&C2);
for(int i=0;i<N;++i)
scanf("%d",&city[i]);
while(M--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
graph[a].push_back(Road(b,c));
graph[b].push_back(Road(a,c));
}
fill(dis,dis+N,INT_MAX);//將最短路徑均設定為最大值
dis[C1]=0;//C1城市是起點,最短路徑為0
pathNum[C1]=1;//C1城市是起點,最短路徑數量為1
teamNum[C1]=city[C1];//C1城市是起點,能夠召集的救護隊數量為本城市的數量
Dijkstra();
printf("%d %d",pathNum[C2],teamNum[C2]);//輸出
return 0;
}
priority_queue lrj版
設m edges,n vertexs
複雜度 mlog(n)
演算法中 ** while(!Q.empty()){} ** 部分使得每個邊都被遍歷到,m。而優先佇列插入複雜度為log(n).故整體mlog(n)
注意m可能大於n^2 最後複雜的>n^2.但不常見
PAT 1003
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include<vector>
using namespace std;
const int maxn = 505 + 5; //vertexs
const int INF = 99999999;
int city[505];
int pathnum[505],teamnum[505];
struct Edge
{
int from,to,dist;
Edge(int f=0,int t=0,int d=0):from(f),to(t),dist(d){}
};
struct HeapNode//優先佇列節點
{
int d,u;
HeapNode(int _d=0,int _u=0):d(_d),u(_u){}
bool operator<(const HeapNode &rhs)const
{
return d>rhs.d;
}
};
struct Dijkstra //邊權為正 負權存在用Bellman-Ford 每兩點間最短路floyd
{
int n,m; //點數和邊數 O(mlog n)
vector<Edge> edges; //邊列表
vector<int> G[maxn]; //每個節點出發的邊編號(編號從0開始)
bool done[maxn]; //是否已永久標號
int d[maxn]; //s到各個點的距離
int p[maxn]; //最短路中的上一條邊
void init(int n)
{
this->n=n;
for(int i=0;i<n;i++)G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int dist)
{
edges.push_back(Edge(from,to,dist));
m=edges.size();
G[from].push_back(m-1);
edges.push_back(Edge(to,from,dist)); //無向圖,雙向
m=edges.size();
G[to].push_back(m-1);
}
void dijkstra(int s) //s start
{
priority_queue<HeapNode> Q; //優先佇列,d[i]越小越先出隊
for(int i=0;i<n;i++)d[i]=INF;
d[s]=0;
memset(done,0,sizeof(done));
Q.push(HeapNode(0,s));
while(!Q.empty()) //第一輪將s能到的點都壓入佇列,之後每次取d[i]最小的點先出(優先佇列)
{
HeapNode x=Q.top();Q.pop();
int u=x.u; //u 當前處理點編號
if(done[u])continue;
done[u]=true;
for(int i=0;i<G[u].size();i++)
{
Edge &e=edges[G[u][i]];
if(d[e.to]>d[u]+e.dist)
{
d[e.to]=d[u]+e.dist; //d[u],出發點s到u的距離
p[e.to]=G[u][i]; //到達e.to點的邊為G[u][i]
Q.push(HeapNode(d[e.to],e.to));
pathnum[e.to]=pathnum[e.from];
teamnum[e.to]=city[e.to]+teamnum[e.from];
}
else if(d[e.to]==d[u]+e.dist){
pathnum[e.to]+=pathnum[e.from];
teamnum[e.to]=max(city[e.to]+teamnum[e.from],teamnum[e.to]);
}
}
}
}
};
int main()
{
Dijkstra dijk;
int n,m,start,end; //n number of vertex m number of edges
cin>>n>>m>>start>>end;
for(int i=0;i<n;i++)
cin>>city[i];
dijk.init(n);
int from,to,dist;
for(int i = 0; i < m; i++) {
scanf("%d%d%d",&from,&to,&dist);
dijk.AddEdge(from,to,dist);
}
pathnum[start]=1;
teamnum[start]=city[start];
dijk.dijkstra(start);
cout<<pathnum[end]<<' '<<teamnum[end];
return 0;
}
6.5.2 SPFA
woj1009
// woj1009
#define INF 0x3f3f3f3f
char word[4005];
int plovers,slovers;
int n, m,edgenum;
const int maxn=105; //const 點的數
struct Edge {
int from, to, power,speed,dist;
char word;
Edge(int u, int v,int p,int s, int d,char word):from(u),to(v),power(p),speed(s),dist(d),word(word){}
};
vector<Edge> edges;
vector<int> G[maxn];
bool inq[maxn]; //是否在佇列裡
int d[maxn]; //s到各個點的距離
int p[maxn]; //最短路中的上一條弧
int cnt[maxn]; //入隊次數 次數大於n則說明有負環
void init(int n) {
edgenum=0;
for(int i = 0; i < n; i++) G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, int power,int speed,int dist,char word) {
edges.push_back(Edge(from, to, power,speed,dist,word));
edgenum = edges.size(); //錯誤,一開始寫成m,而m又是全域性變數導致下面data()的迴圈除了問題
G[from].push_back(edgenum-1); //邊的標號
}
//拓撲排序可以判斷有向圖有沒有環
//dfs判斷圖聯通
bool bellman_ford(int s) { ///BF 適用於含有負邊的圖。如果有負邊,返回false。Dijkstra演算法無法判斷含負權邊的圖的最短路.二者都適用於有向有環圖
queue<int> Q;
memset(inq, 0, sizeof(inq));
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < n; i++) d[i] = INF;
d[s] = 0;
inq[s] = true;
p[s]=-1; //加了一條
Q.push(s);
while(!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = false;
for(int i = 0; i < G[u].size(); i++) {
Edge& e = edges[G[u][i]];
if(d[u] < INF && d[e.to] > d[u] + e.dist&&plovers>e.power&&slovers>e.speed) { //模板,+條件
d[e.to] = d[u] + e.dist;
p[e.to] = G[u][i];
if(!inq[e.to]) { Q.push(e.to); inq[e.to] = true; if(++cnt[e.to] > n) return false;}
}
}
}
vector<char>ans; //也可以寫一個函式遞迴,沒必要
int tmp=p[n-1];
while(tmp!=-1){
ans.push_back(edges[tmp].word);
tmp=p[edges[tmp].from];
}
for(int i=ans.size()-1;i>-1;i--)
cout<<ans[i];
cout<<endl;
return true;
}
void data(){
init(n);
int from,to,power,speed,dist,tmp;
char word;
for(int i=0;i<m;i++){
/* 這樣寫有問題。讀了空格
scanf("%d%d%d%d%d",&from,&to,&power,&speed,&dist);
scanf("%c",&word);
*/
/*
scanf("%d%d%d%d%d",&from,&to,&power,&speed,&dist);
getchar();scanf("%c",&word);getchar();*/ //處理最後一個字元前的空格這樣可以,但是麻煩
scanf("%d %d %d %d %d %c",&from,&to,&power,&speed,&dist,&word); //注意%c不是%s 。也可以fstream
AddEdge(from,to,power,speed,dist,word);
}
cin>>plovers>>slovers;
bellman_ford(0);
}
6.6 生成樹
6.7 如何建圖?
鄰接矩陣 //資料範圍很大,不能用鄰接矩陣
鄰接表
鄰接表可以用 連結串列或者 vector 見 woj1006
vector<int>mapp;
for(int i=0;i<n;i++)
mapp[i].clear();
for(int i=0;i<m;i++){
scanf("%d%d", &x, &y); mapp[x].push_back(y); mapp[y].push_back(x);
}
紫書模板建圖 見我的題解 woj1009
一般的用vector[i]表示i所連邊 見我的題解 woj1024
7. Sort
https://www.cnblogs.com/lqerio/p/13484897.html
8. greedy 貪心
https://www.cnblogs.com/lqerio/p/11749926.html
9. 字串 string
9.1 KMP
9.2 AC 自動機
9.3 字典序 Dictionary order
https://www.cnblogs.com/lqerio/p/11785894.html
sort,strcmp,string
woj1013
字典序全排列生成:https://www.cnblogs.com/lqerio/p/12079873.html
比較可以用sort(qsort不推薦)
bool cmp(char*a,char*b){
return strcmp(a,b);
}
bool cmp1(string a,string b){
return a<b;
}
vector<string>ans;
sort(ans.begin(),ans.end(),cmp1);
9.4 leetcode5 Manacher法 最長迴文字串
https://www.cnblogs.com/lqerio/p/11723652.html
10. 網路流
見woj1008.
11. kth biggest/smallest
https://www.cnblogs.com/lqerio/p/9757284.html
12. others
12.1 make an structure of O(1) search,insert,delete
leetcode381
12.2 GCD
int gcd(int a,int b)
{
// return (b==0)?gcd(b,a%b):a
if(b==0)
return a;
else
return gcd(b,a%b);
}
12.3 Prime
bool isPrime(int n) {
if (n < 2)
return false;
int m=sqrt(n+0.5);
for (int i = 2; i <= m; i++) {
if (n % i == 0)
return false;
}
return true;
}
void euler_sieve(int n) //線性篩
{
totPrimes = 0;
memset(flag, 0, sizeof(flag));
for (int i = 2; i <= n; i++) {
if (!flag[i])
primes[totPrimes++] = i;
for (int j = 0; i * primes[j] <= n; j++) {
flag[i*primes[j]] = true;
if (i % primes[j] == 0)
break;
}
}
}
void eratosthenes_sieve(int n)
{
totPrimes = 0;
memset(flag, 0, sizeof(flag));
int sqrtn = sqrt(n + 0.5);
for (int i = 2; i <= sqrtn; i++) {
if (!flag[i]) {
primes[totPrimes++] = i;
for (int j = i * i; j <= n; j += i) {
flag[j] = true;
}
}
}
for (int i = sqrtn + 1; i <= n; i++) {
if (!flag[i])
primes[++totPrimes] = i;
}
}
12.4 binary_search
int binarysearch(int x)
{
int l=0,r=n*n;
while(r-l>=1)
{
int i=(r+l)/2;
if(num[i]==x) return 1;
else if(num[i]<x) l=i+1;
else r=i;
}
return 0;
}
12.5 pow
ll pow(ll a,ll n) //a^n
{
ll result=1,flag=a;
while(n!=0)
{
if(n&1)
result=result*flag;
flag=flag*flag;
n=n>>1;
}
return result;
}
ll pow(ll a,ll n,ll b) //a^n %b to avoid Integer overflow
{
ll result=1;
a=a%b;
while(n>0)
{
if(n%2==1)
result=result*a%b;
n=n/2;
a=a*a%b;
}
return result;
}
12.6 floating numbers
uva11809
https://blog.csdn.net/crazysillynerd/article/details/43339157
#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
using namespace std;
int main() {
double M[20][40];
long long E[20][40];
// 打表
for(int i = 0; i <= 9; ++i) for(int j = 1; j <= 30; ++j) {
double m = 1 - pow(2, -1 - i), e = pow(2, j) - 1;
double t = log10(m) + e * log10(2);
E[i][j] = t, M[i][j] = pow(10, t - E[i][j]);
}
// 輸入並輸出結果
string in;
while(cin >> in && in != "0e0") {
// 處理輸入
for(string::iterator i = in.begin(); i != in.end(); ++i) if(*i == 'e') *i = ' ';
istringstream ss(in);
double A; int B;
ss >> A >> B;
while(A < 1) A *= 10, B -= 1;
// 在打好的表中尋找答案
for(int i = 0; i <= 9; ++i) for(int j = 1; j <= 30; ++j) {
if(B == E[i][j] && (fabs(A - M[i][j]) < 1e-4 || fabs(A / 10 - M[i][j]) < 1e-4)) {
cout << i << ' ' << j << endl;
break;
}
}
}
}
12.7 high accuracy
https://www.cnblogs.com/ECJTUACM-873284962/p/6509429.html
uva 1828 fibonacci
https://www.xuebuyuan.com/1888279.html
#include <iostream>
#include <string.h>
using namespace std;
int f[5010][1010]; //第1個5010用來存5010個斐波那契數(測試可知第5000項已超過了1000位),第2個1010表示給每個斐波那契數開1010位
int main()
{
int i, j;
memset(f, 0, sizeof(f));
f[1][0] = 1; //給第1個斐波那契數置數
f[2][0] = 1; //給第2個斐波那契數置數
for(i = 3; i < 5010; i++) //從第3項開始,用前2項相加
{
int C = 0; //C表示進位,開始設為0
for(j = 0; j < 1001; j++)
{
f[i][j] = (f[i-2][j] + f[i-1][j] + C) % 10; //%10後就是這一位該有的數字
C = (f[i-2][j] + f[i-1][j] + C) / 10; //相加產生的進位
}
}
int a;
while(cin>>a)
{
for(j = 1001; j >= 0; j--) //尋找最高位
if(f[a][j] != 0)
break;
for(; j >= 0; j--)
cout<<f[a][j];
cout<<endl;
}
return 0;
}
12.8 big number //JAVA and PYTHON are highly recommended
https://www.cnblogs.com/lqerio/p/11117608.html
12.9 c++ stl
https://www.cnblogs.com/lqerio/p/13484897.html
https://www.cnblogs.com/lqerio/p/11117601.html
12.10 滑動視窗 Sliding window
https://www.cnblogs.com/lqerio/p/11708680.html
https://www.cnblogs.com/lqerio/p/9741044.html