文章目录

  • 头文件
  • 快读
  • 素数筛法
    • 埃筛
    • 欧筛
  • 快速幂
  • GCD and LCM
  • DP板子
    • 01 01 01 背包
    • 完全背包
    • 多重背包
      • 朴素
      • 二进制优化
    • 分组背包
    • 背包方案数
  • 并查集
  • 最短路
    • 单源最短路Dijkstra
    • 弗洛伊德最短路
    • SPFA
  • 二分图
    • 染色法
    • 匈牙利算法
  • 最小生成树
    • Kruskal
    • Prim
  • 欧拉函数
    • 埃筛求欧拉函数
    • 欧筛求欧拉函数
  • 线段树
  • 计算几何
    • 向量基本用法
    • 求多边形面积
    • 判断线段相交
    • 求解三角形外心
    • 极角排序
  • 字符串
  • 博弈论
    • 巴什博弈
    • 威佐夫博弈
    • 尼姆博弈
    • 斐波拉契博弈
    • 环形博弈
    • 对称博弈

头文件

#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define pii pair<int,int>
#define ll long long
#define inf 1e9
using namespace std;
const int N = 2e5+10;

快读

template <class T>
inline void read(T &res)
{char c;T flag = 1;while ((c = getchar()) < '0' || c > '9')if (c == '-')flag = -1;res = c - '0';while ((c = getchar()) >= '0' && c <= '9')res = res * 10 + c - '0';res *= flag;
}

素数筛法

埃筛

int vis[N];
int prime[N];
void Ai_init(int x){for(int i = 2;i <= N;i++){if(!vis[i]){prime[++prime[0]] = i;//prime[i]表示素数个数int l = 2;while(l*i <= N){vis[l*i] = 1;l++;}}}
}

欧筛

int vis[N];
int prime[N];
void Ou_init(int x){for(int i = 2;i<=N/2;i++){if(!vis[i])prime[++prime[0]] = i;for(int j = 1;j <= prime[0]&&j*i<=N;j++){vis[i*prime[j]] = 1;if(i%prime[j]==0)break;}}
}

快速幂

ll binpow(ll a, ll b, ll c){ll res = 1;'while(b){if(b&1)res = res*a%c;a = (a*a)%c;b >>= 1;}return res;
}

GCD and LCM

int gcd(int a, int b){int c = a%b;while(c){a = b;b = c;c = a % b;}return b;
}
int lcm(int a, int b){return a*b/gcd(a,b);
}

DP板子

01 01 01 背包

int n, m, k;
int v[N], w[N], dp[N];
void solve()
{cin>>n>>k;for(int i = 1;i <= n;i++)cin>>v[i]>>w[i];for(int i = 1;i <= n;i++){for(int j = k;j >= v[i];j--){dp[j] = max(dp[j],dp[j-v[i]]+w[i]);}}cout<<dp[k]<<endl;}

完全背包

int v[N], w[N], dp[N];
void solve()
{cin>>n>>k;for(int i = 1;i <= n;i++)cin>>v[i]>>w[i];for(int i = 1;i <= n;i++){for(int j = v[i];j <= k;j++){dp[j] = max(dp[j],dp[j-v[i]]+w[i]);}}cout<<dp[k]<<endl;}

多重背包

朴素
void solve()
{cin>>n>>m;for(int i = 1;i <= n;i++)cin>>v[i]>>w[i]>>s[i];for(int i = 1;i <= n;i++){for(int j = 0;j <= m;j++){for(int k = 0;k <= s[i]&&k*v[i]<=j;k++){dp[i][j] = max(dp[i][j],dp[i-1][j-v[i]*k]+w[i]*k);}}}cout<<dp[n][m]<<endl;
}
二进制优化
int v[N], w[N], dp[N];
void solve()
{cin>>n>>m;int cnt = 0;for(int i = 1;i <= n;i++){int a, b, s;cin>>a>>b>>s;int k = 1;while(k <= s){cnt++;v[cnt] = a*k;w[cnt] = b*k;s -= k;k *= 2;}if(s > 0){cnt++;v[cnt] = a*s;w[cnt] = b*s;}}n = cnt;//更新物品数量,因为我们用二进制优化打包了物品for(int i = 1;i <= n;i++){for(int j = m;j >= v[i];j--){dp[j] = max(dp[j], dp[j-v[i]]+w[i]);}}cout<<dp[m]<<endl;
}

分组背包

int v[N][N], w[N][N], s[N], dp[N];
void solve()
{cin>>n>>m;for(int i = 1;i <= n;i++){cin>>s[i];for(int j = 0;j < s[i];j++){cin>>v[i][j]>>w[i][j];}}for(int i = 1;i <= n;i++){for(int j = m;j >= 0;j--){for(int k = 0;k < s[i];k++){if(v[i][k] <= j)dp[j] = max(dp[j],dp[j-v[i][k]]+w[i][k]);}}}cout<<dp[m]<<endl;}

背包方案数

int v[N], w[N], dp[N][N], pl[N][N];
void solve()
{cin>>n>>m;for(int i = 1;i <= n;i++)cin>>v[i]>>w[i];for(int i = 1;i <= n;i++){for(int j = 0;j <= m;j++){dp[i][j] = dp[i-1][j];if(j >= v[i])dp[i][j] = max(dp[i][j],dp[i-1][j-v[i]]+w[i]);}}pl[0][0] = 1;for(int i = 1;i <= n;i++){for(int j = 0;j <= m;j++){if(dp[i][j]==dp[i-1][j])pl[i][j] = (pl[i][j]+pl[i-1][j])%mod;if(j>=v[i]&&dp[i][j]==dp[i-1][j-v[i]]+w[i])pl[i][j] = (pl[i][j]+pl[i-1][j-v[i]])%mod;}}int ans = 0;for(int i = 0;i <= m;i++){if(dp[n][i]==dp[n][m])ans=(ans+pl[n][i])%mod;}cout<<ans<<endl;
}

并查集

int pre[N];
void init(int x){for(int i = 1;i <= x;i++){pre[i] = i;}
}
int find(int x){if(x!=pre[x])pre[x] = find(pre[x]);return pre[x];
}
void merge(int a, int b){a = find(a), b = find(b);pre[a] = b;
}

最短路

单源最短路Dijkstra

#include <bits/stdc++.h>
#include <algorithm>
#define ll long long
#define pii pair<int, int>
#define inf 1e9
using namespace std;
const int N = 2e5+10;
const int mod = 1e9 + 7;
int t, n, m, s;
// 建立邻接表
int vis;
struct node{int u, v, w, nex;
}idex[N];
int head[N];
bool vim[N/2];
ll dis[N/2];
void add(int a, int b, int w){idex[++vis].u = a;idex[vis].v = b;idex[vis].w = w;idex[vis].nex = head[a];head[a] = vis;
}
// 迪杰斯特拉
priority_queue<pii,vector<pii>,greater<pii>>q;
void dijkstra(){for(int i = 1;i <= n;i++)dis[i] = inf;dis[s] = 0;pii f = make_pair(0,s);q.push(f);while(!q.empty()){int top = q.top().second;q.pop();if(vim[top])continue;vim[top] = true;for(int i = head[top];i;i = idex[i].nex){int ind = idex[i].v;if(dis[ind] > dis[top]+idex[i].w){dis[ind] = dis[top]+idex[i].w;q.push(make_pair(dis[ind],ind));}}}
}
void solve(){cin>>n>>m>>s;for(int i = 0;i < m;i++){int a, b, c;cin>>a>>b>>c;add(a,b,c);}dijkstra();for(int i = 1;i <= n;i++)cout<<dis[i]<<" ";
}
int main()
{// cin>>t;// while(t--)solve();return 0;
}

弗洛伊德最短路

void func(){int dis[N][N];memset(dis,inf,sizeof(dis));for(int i = 0;i < n;i++){for(int j = 0;j < n;j++){cin>>dis[i][j];}}for(int k = 0;k < n;k++)for(int i = 0;i < n;i++)for(int j = 0;j < n;j++)dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);//弗洛伊德就是暴力枚举最小值
}

SPFA

vector<node> G[maxn];
bool inqueue[maxn];
int dist[maxn];void Init()
{  for(int i = 0 ; i < maxn ; ++i){  G[i].clear();  dist[i] = INF;  }
}
int SPFA(int s,int e)
{  int v1,v2,weight;  queue<int> Q;  memset(inqueue,false,sizeof(inqueue)); // 标记是否在队列中 memset(cnt,0,sizeof(cnt)); // 加入队列的次数 dist[s] = 0;  Q.push(s); // 起点加入队列 inqueue[s] = true; // 标记 while(!Q.empty()){  v1 = Q.front();  Q.pop();  inqueue[v1] = false; // 取消标记 for(int i = 0 ; i < G[v1].size() ; ++i){ // 搜索v1的链表 v2 = G[v1][i].vex;  weight = G[v1][i].weight;  if(dist[v2] > dist[v1] + weight){ // 松弛操做 dist[v2] = dist[v1] + weight;  if(inqueue[v2] == false){  // 再次加入队列 inqueue[v2] = true;  //cnt[v2]++; // 判负环 //if(cnt[v2] > n) return -1; Q.push(v2);  } } }  }  return dist[e];
}

二分图

染色法

int bipartite(int s) {  int u, v;  queue<int>Q;  color[s] = 1;  Q.push(s);  while (!Q.empty()) {  u = Q.front();  Q.pop();  for (int i = 0; i < G[u].size(); i++) {  v = G[u][i];  if (color[v] == 0) {  color[v] = -color[u];  Q.push(v);  }  else if (color[v] == color[u])  return 0;  }  }  return 1;
}

匈牙利算法

vector<int>G[maxn];
bool inpath[maxn];  // 标记
int match[maxn];    // 记录匹配对象
void init()
{  memset(match, -1, sizeof(match));  for (int i = 0; i < maxn; ++i) {  G[i].clear();  }
}
bool findpath(int k) {  for (int i = 0; i < G[k].size(); ++i) {  int v = G[k][i];  if (!inpath[v]) {  inpath[v] = true;  if (match[v] == -1 || findpath(match[v])) { // 递归 match[v] = k; // 即匹配对象是“k妹子”的 return true;  }  }  }  return false;
}  void hungary() {  int cnt = 0;  for (int i = 1; i <= m; i++) {  // m为须要匹配的“妹子”数 memset(inpath, false, sizeof(inpath)); // 每次都要初始化 if (findpath(i)) cnt++;  }  cout << cnt << endl;
}
int v1, v2;
bool Map[501][501];
bool visit[501];
int link[501];
int result;  bool dfs(int x)  {  for (int y = 1; y <= v2; ++y)  {  if (Map[x][y] && !visit[y])  {  visit[y] = true;  if (link[y] == 0 || dfs(link[y]))  {  link[y] = x;  return true;  } } }  return false;
}  void Search()  {  for (int x = 1; x <= v1; x++)  {  memset(visit,false,sizeof(visit));  if (dfs(x))  result++;  }
}

最小生成树

Kruskal

#include<bits/stdc++.h>
#include<algorithm>
#include<functional>
#define inf 1e9
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 2e5+10;
const int mod = inf+7;
int t, n, m, k;
int ans;
struct edge{int u, v, w;edge(int x, int y, int z):u(x), v(y), w(z){};
};
vector<edge> L;
vector<edge> res;
int pre[N];
bool vis[N];
bool cmp(edge x, edge y){return x.w < y.w;
}
int find(int x){if(x!=pre[x])pre[x] = find(pre[x]);return pre[x];
}
void kruskal(){for(int i = 1;i <= n;i++){pre[i] = i;}for(int i = 0;i < m;i++){int a = find(L[i].u);int b = find(L[i].v);if(a != b){res.push_back(L[i]);ans += L[i].w;pre[a] = b;}}
}
void solve(){cin>>n>>m;for(int i = 0;i < m;i++){int a, b, c;cin>>a>>b>>c;L.push_back(edge(a,b,c));}sort(L.begin(),L.end(),cmp);kruskal();if(res.size() < n-1)cout<<"orz\n";else cout<<ans<<"\n";
}
int main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);// cin>>t;t = 1;while(t--)solve();return 0;
}

Prim

struct node {  int v, len;  node(int v = 0, int len = 0) :v(v), len(len) {}  bool operator < (const node &a)const {  // 加入队列的元素自动按距离从小到大排序 return len> a.len;  }
};
vector<node> G[maxn];
int vis[maxn];
int dis[maxn];
void init() {  for (int i = 0; i<maxn; i++) {  G[i].clear();  dis[i] = INF;  vis[i] = false;  }
}
int Prim(int s) {  priority_queue<node>Q; // 定义优先队列 int ans = 0;  Q.push(node(s,0));  // 起点加入队列 while (!Q.empty()) {   node now = Q.top(); Q.pop();  // 取出距离最小的点 int v = now.v;  if (vis[v]) continue;  // 同一个节点,可能会推入2次或2次以上队列,这样第一个被标记后,剩下的须要直接跳过。 vis[v] = true;  // 标记一下 ans += now.len;  for (int i = 0; i<G[v].size(); i++) {  // 开始更新 int v2 = G[v][i].v;  int len = G[v][i].len;  if (!vis[v2] && dis[v2] > len) {   dis[v2] = len;  Q.push(node(v2, dis[v2]));  // 更新的点加入队列并排序 }  }  }  return ans;
}

欧拉函数

欧拉函数是小于 x x x 的整数中与 x x x 互质的数的个数,用 H ( x ) H(x) H(x) 表示, H ( 1 ) = 1 H(1) = 1 H(1)=1 。

计算通式: H ( x ) = x × ∏ i = 1 n ( 1 − 1 p i ) H(x) = x\times \prod_{i=1}^n(1-\frac{1}{p_i}) H(x)=x×∏i=1n​(1−pi​1​) (其中 p i p_i pi​ 为 x x x 的所有质因数)

埃筛求欧拉函数

const int N = 1e5+10;
int phi[N];
void euler(int n){for(int i = 1;i <= n;i++)phi[i] = i;for(int i = 2;i <= n;i++){if(i == phi[i]){for(int j = i;j <= n;j += i){phi[j] = phi[j]/i*(i-1);}}}
}

欧筛求欧拉函数

const int N = 1e5+10;
int phi[N];
int prime[N];
bool vis[N];
void euler(int n){phi[1] = 1;for(int i = 2;i <= n;i++){if(!vis[i]){prime[++prime[0]] = i;phi[i] = i-1;}for(int j = 1;j <= prime[0]&&prime[j]*i<=n;j++){vis[i*prime[j]] = 1;if(!i%prime[j]){phi[i*prime[j]] = phi[i]*prime[j];break;}else{phi[i*prime[j]] = phi[i]*phi[prime[j]];}}}
}

线段树

#include<bits/stdc++.h>
#include<algorithm>
#define inf 1e9
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 5e5+10;
int n, m, t, s;
int a[N];
int ans;
struct segment_tree
{//节点,存储左右儿子和该节点的值struct node{int l, r,sum;int lz;//懒标记}tr[N*4];// 建立线段树void build(int p, int l, int r){tr[p].l = l, tr[p].r = r;if(l == r){tr[p].sum = a[l];return ;}int mid = (l+r)>>1;build(p<<1,l,mid);build(p<<1|1,mid+1,r);// 该节点的权值为左右儿子的权值之和tr[p].sum = tr[p<<1].sum + tr[p<<1|1].sum;}
// 类型一// 区间查询int search(int p, int l, int r){if(tr[p].l >= l&&tr[p].r <= r){return tr[p].sum;}if(tr[p].r < l||tr[p].l > r)return 0;int s = 0;if(tr[p<<1].r >= l) s += search(p<<1,l,r);if(tr[p<<1|1].l <= r) s += search(p<<1|1,l,r); return s;}// 单点修改void add(int p, int dis, int k){if(tr[p].l==tr[p].r){tr[p].sum += k;return ;}if(dis <= tr[p<<1].r)add(p<<1,dis,k);else add(p<<1|1,dis,k);tr[p].sum = tr[p<<1].sum+tr[p<<1|1].sum;//更新对应父节点的值return ;}
// 类型二// 区间修改void modify(int p, int l, int r, int k){if(tr[p].l >= l&&tr[p].r <= r){tr[p].sum += k;tr[p].lz += k;return ;}int mid = l+r>>1;if(l <= mid) modify(p<<1,l,r,k);if(r > mid) modify(p<<1|1,l,r,k);}// 单点查询void query(int p, int x){ans += tr[p].sum;if(tr[p].l==tr[p].r)return ;int mid = tr[p].l+tr[p].r>>1;if(x <= mid)query(p<<1,x);else query(p<<1|1,x);}
// 类型三void push_down(int p){if(tr[p].lz!=0){tr[p<<1].lz += tr[p].lz;tr[p<<1|1].lz += tr[p].lz;int mid = tr[p].l+tr[p].r>>1;tr[p<<1].sum += tr[p].lz*(mid - tr[p<<1].l+1);tr[p<<1|1].sum += tr[p].lz*(tr[p<<1|1].l-mid);tr[p].lz = 0;}}//区间修改 void modifycpy(int p, int l, int r, int k){if(tr[p].r <= r&&tr[p].l >= l){tr[p].sum += k*(tr[p].r-tr[p].l+1);tr[p].lz += k;return ;}push_down(p);if(tr[p<<1].r >= l)modifycpy(p<<1,l,r,k);if(tr[p<<1|1].l <= r)modifycpy(p<<1|1,l,r,k);tr[p].sum = tr[p<<1].sum + tr[p<<1|1].sum;}   //区间查询int searchcpy(int p, int l,int r){if(tr[p].l >= l&&tr[p].r <= r){return tr[p].sum;}if(tr[p].r < l||tr[p].l > r)return 0;push_down(p);int res = 0;if(tr[p<<1].r >= l)res += searchcpy(p<<1,l,r);if(tr[p<<1|1].l <= r)res += searchcpy(p<<1|1,l,r);return res;}
}ST;
void solve(){cin>>n;for(int i = 1;i <= n;i++)cin>>a[i];ST.build(1,1,n);for(int i = 1;i <= 4;i++){int x, y;cin>>x>>y;int ans = ST.search(1,x,y);cout<<ans<<"\n";}
}
int main(){solve();return 0;
}

计算几何

向量基本用法

struct node {  double x; // 横坐标 double y; // 纵坐标
};  typedef node Vector;Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator - (Point A, Point B) { return Vector(A.x - B.y, A.y - B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y*p); }  double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; } // 向量点乘
double Length(Vector A) { return sqrt(Dot(A, A)); }  // 向量模长
double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); }  // 向量之间夹角 double Cross(Vector A, Vector B) { // 叉积计算 公式 return A.x*B.y - A.y*B.x;
}  Vector Rotate(Vector A, double rad) // 向量旋转 公式 { return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}  Point getLineIntersection(Point P, Vector v, Point Q, Vector w) { // 两直线交点t1 t2计算公式 Vector u = P - Q;   double t = Cross(w, u) / Cross(v, w);  // 求得是横坐标 return P + v*t;  // 返回一个点
}

求多边形面积

node G[maxn];
int n;  double Cross(node a, node b) { // 叉积计算 return a.x*b.y - a.y*b.x;
}  int main()
{  while (scanf("%d", &n) != EOF && n) {  for (int i = 0; i < n; i++)   scanf("%lf %lf", &G[i].x, &G[i].y);  double sum = 0;  G[n].x = G[0].x;  G[n].y = G[0].y;  for (int i = 0; i < n; i++) {   sum += Cross(G[i], G[i + 1]);  }  // 或者 //for (int i = 0; i < n; i++) { //sum += fun(G[i], G[(i + 1)% n]); //} sum = sum / 2.0;  printf("%.1f\n", sum);  }  system("pause");  return 0;
}

判断线段相交

node P[35][105]; double Cross_Prouct(node A,node B,node C) {     //  计算BA叉乘CA     return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
}
bool Intersect(node A,node B,node C,node D)  {  //  经过叉乘判断线段是否相交;           if(min(A.x,B.x)<=max(C.x,D.x)&&         //  快速排斥实验;      min(C.x,D.x)<=max(A.x,B.x)&&      min(A.y,B.y)<=max(C.y,D.y)&&      min(C.y,D.y)<=max(A.y,B.y)&&      Cross_Prouct(A,B,C)*Cross_Prouct(A,B,D)<0&&      //  跨立实验;      Cross_Prouct(C,D,A)*Cross_Prouct(C,D,B)<0)       //  叉乘异号表示在两侧;      return true; else return false;
}

求解三角形外心

Point circumcenter(const Point &a, const Point &b, const Point &c) { //返回三角形的外心        Point ret; double a1 = b.x - a.x, b1 = b.y - a.y, c1 = (a1*a1 + b1*b1) / 2; double a2 = c.x - a.x, b2 = c.y - a.y, c2 = (a2*a2 + b2*b2) / 2; double d = a1*b2 - a2*b1; ret.x = a.x + (c1*b2 - c2*b1) / d; ret.y = a.y + (a1*c2 - a2*c1) / d; return ret;
}

极角排序

double cross(point p1, point p2, point q1, point q2) {  // 叉积计算 return (q2.y - q1.y)*(p2.x - p1.x) - (q2.x - q1.x)*(p2.y - p1.y);
}
bool cmp(point a, point b)  {  point o;  o.x = o.y = 0;  return cross(o, b, o, a) < 0; // 叉积判断
}
sort(convex + 1, convex + cnt, cmp); // 按角排序, 从小到大

字符串

博弈论

巴什博弈

巴什博奕:只有一堆 n n n 个物品,两个人轮流从中取物,规定每次最少取一个,最多取 m m m 个,最后取光者为胜。

if(n%(m+1)==0)  cout<<"后手必胜"<<endl;
else cout<<"先手必胜"<<endl;

解释:一轮最多拿的就是 1 + m 1+m 1+m 个,所以控制下去,最后的不到( 1 + m 1+m 1+m)的物品肯定会被后手拿到的。

威佐夫博弈

有两堆各若干的物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同件物品,规定最后取完者胜利。

解题核心就是:看两个数的差值 t t t 是不是满足 $\frac{(sqrt(5)+1)}{2}\times t=min(n1,n2) $ ;

#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
int main()
{  int n1,n2,temp;  while(cin>>n1>>n2)  {  if(n1>n2)  swap(n1,n2);  temp=floor((n2-n1)*(1+sqrt(5.0))/2.0);  if(temp==n1) cout<<"后手必胜"<<endl;  else cout<<"先手必胜"<<endl;  }  return 0;
}

尼姆博弈

有任意堆物品,每堆物品的个数是任意的,双方轮流从中取物品,每一次只能从一堆物品中取部分或全部物品,最少取一件,取到最后一件物品的人获胜。

解题核心:把每堆物品数全部异或起来,如果得到的值为 0 0 0 ,那么先手必败,否则先手必胜。

#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
int main()
{  int n,ans,temp;  while(cin>>n)  {  temp=0;  for(int i=0;i<n;i++)  {  cin>>ans;  temp^=ans;  }  if(temp==0)  cout<<"后手必胜"<<endl;  else cout<<"先手必胜"<<endl;  }  return 0;
}

斐波拉契博弈

有一堆物品,两人轮流取物品,先手最少取一个,至多无上限,但不能把物品取完,之后每次取的物品数不能超过上一次取的物品数的二倍且至少为一件,取走最后一件物品的人获胜。

解题核心:先手胜当且仅当n不是斐波那契数( n n n 为物品总数)

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int N = 55;
int f[N];
void Init()
{    f[0] = f[1] = 1;    for(int i=2;i<N;i++)    f[i] = f[i-1] + f[i-2];
}
int main()
{    Init();    int n;    while(cin>>n)    {    if(n == 0) break;    bool flag = 0;    for(int i=0;i<N;i++)    {    if(f[i] == n)    {    flag = 1;    break;    }    }    if(flag) puts("Second win");    else     puts("First win");    }    return 0;
}

环形博弈

n个石子围成一个环,每次取一个或者取相邻的2个。

解题核心:石子数目小于等于2 先手胜,其他 后手胜。

对称博弈

n n n个石子围成环,每次只能取相邻的 1 1 1 ~ k k k 个 。

( 1 ) (1) (1) 如果 k < n k<n k<n :

如果 k = 1 k = 1 k=1,如果 n % 2 = 0 n\%2=0 n%2=0 ,则后手赢。

如果 k > 1 k > 1 k>1,后手赢。(先手取什么位置后手就取对称的位置,这样保证后手永远能取到 )

( 2 ) (2) (2) 如果 n ≤ k n\leq k n≤k:

先手赢

ACM基本算法板子记录相关推荐

  1. ACM 全部算法总结

    ACM 所有算法 附带我学过的算法的博客链接 数据结构 栈 队列 链表 哈希表 哈希数组 堆 优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平 ...

  2. acm常见算法及例题

    1 acm常见算法及例题 2 3 初期: 4 一.基本算法: 5 (1)枚举. (poj1753,poj2965) 6 (2)贪心(poj1328,poj2109,poj2586) 7 (3)递归和分 ...

  3. ACM所有算法大全(持续更新)

    转载自: http://blog.sina.com.cn/s/blog_adb6743801019h29.html ACM 所有算法 数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 ...

  4. ACM常用算法及练习

    ACM常用算法及练习 (想学请先放弃) 第一阶段:练bai经典常用算法,下面的每个算法给我打上十du到二十遍,同时自己精简zhi代码 1.最短路(Floyd.Dijstra,BellmanFord) ...

  5. 暑期集训2:ACM基础算法 练习题G:POJ - 1298

    2018学校暑期集训第二天--ACM基础算法 练习题G  --  POJ - 1298 The Hardest Problem Ever Julius Caesar lived in a time o ...

  6. 暑期集训2:ACM基础算法 练习题C:CF-1008A

    2018学校暑期集训第二天--ACM基础算法 练习题A  --   CodeForces - 1008A Romaji Vitya has just started learning Berlanes ...

  7. 暑期集训2:ACM基础算法 练习题B:CF-1008B

    2018学校暑期集训第二天--ACM基础算法 练习题B  --   CodeForces - 1008B Turn the Rectangles There are nn rectangles in ...

  8. 暑期集训2:ACM基础算法 练习题A:CF-1008C

    2018学校暑期集训第二天--ACM基础算法 练习题A  --  CodeForces - 1008C Reorder the Array You are given an array of inte ...

  9. 暑期集训2:ACM基础算法 例2:POJ-2456

    2018学校暑期集训第二天--ACM基础算法 例二  --   POJ - 2456 Aggressive cows Farmer John has built a new long barn, wi ...

最新文章

  1. 把Excel文件中的数据读入到DataGrid中
  2. layui 按钮点击一次后失效_00017-layui 对话框 layer.open 点击保存,按钮失效,保存完后,再恢复...
  3. Natasha 4.0 探索之路系列(一) 概况
  4. 群辉挂载linux nfs,Debian 9 挂载访问已设置的群晖NFS共享文件目录
  5. 《大数据》2015年第3期“研究”——社交网络影响力传播研究(下)
  6. python做插件应用_Python插件机制实现详解
  7. 机器视觉与Tesseract介绍
  8. STM32工作笔记0060---窗口看门狗实验
  9. @程序员,如何用最少的字节编写 C64 可执行文件?
  10. 疫情下的创业品牌如何逆风翻盘?
  11. 易语言获取链接的真实地址_ret2libc过地址随机化
  12. 计算机网络原理笔记精整理(汇总)
  13. Android热修复技术——QQ空间补丁方案解析(2)
  14. 利用python+迅雷批量下载视频
  15. Python构造虚数矩阵报警告ComplexWarning: Casting complex values to real discards the imaginary part
  16. JSON.parse和evel的区别
  17. 谷歌seo关键词排名优化指南【2023年新版】
  18. JPA实体继承实体的映射策略
  19. 【Matlab语音加密】语音信号加密解密(带面板)【含GUI源码 181期】
  20. 面试官:抽象工厂模式是什么?

热门文章

  1. 一般人不告诉他——程序员职场黑话
  2. 紧急用钱?我觉得可以考虑广发财智金
  3. i5-1035g1和i5-8265u参数对比哪个好
  4. Majing-2017ACL-Detect Rumors in Microblog Posts Using Propagation Structure via Kernel Learning
  5. 数组——排序(选择法)
  6. 利用瑞芯微3399Pro推理yoloV5s目标检测模型:踩坑笔记
  7. react hooks介绍以及常用hooks列举
  8. nvidia+cuda+cudnn+pytorch安装流程(外加ubuntu黑屏解决方案)
  9. 手机GPU光追新解:详谈Imagination刚发布的DXT架构
  10. 泰安市住建局发布关于绿色建筑发展专项规划