直接写个合集吧, 单独写可能300字都不够(迫真

A. 青蛙过河

题目太长了, 去看了下别人解释的题意
简单来说就是在石墩上青蛙可以类似Hanoi问题(汉诺塔)地叠着
我们想叠得越多越好,显然我们既然有办法把它叠起来,用叠的逆过程就可以把它们全部合法的放到河对岸

  • , 每个荷叶一只青蛙,一只青蛙直接跳到对岸,有
  • , 在石墩上放 只青蛙, 问题被分解为

于是很容易得到每多一个石墩, 都可以把原来 个石墩的青蛙转移到上面来, 数量翻倍
得到答案

#include<bits/stdc++.h>

typedef long long ll;

using namespace std;

const ll mod = 1e9 + 7;
const int N = 2e5 + 5;

int main() {
  ll n, m;
  cin >> n >> m;
  cout << (m + 1) * (1LL << n) << "\n";
  return 0;
}

B. 华华对月月的忠诚

Solution

直接手推几项,
不难看出 , 我们要求
因为, 互为斐波那契数列的相邻两项, 显然互质
所以, 前面的系数 不用看, 显然答案为

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
  ios::sync_with_stdio(false), cin.tie(nullptr);
  ll a, b;
  string s;
  cin >> a >> b >> s;
  cout << __gcd(a, b) << "\n";
  return 0;
}

C. Game

Solution

进行质因数分解, 判断质因子奇偶性即可

Code

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef unsigned long long ll;
static auto faster_iostream = []() {
    std::ios::sync_with_stdio(false);  // turn off sync
    std::cin.tie(nullptr);             // untie in/out streams
    return 0;
}();
const int N = 2e5 + 5;
const int mod = 20010905;
int main(){
    int n;
    while(cin >> n){
        int flag = 0;
        int cnt = 0;
        for(int i = 2; i * i <= n; i++){
            if(n % i == 0){
                flag = 1;
                while(n % i == 0){
                    n /= i;
                    cnt++;
                }
            }
        }
        if(n > 1){
            cnt++;
        }
        //cout << cnt << endl;
        if(!flag){
            cout << "Nancy" << endl;
        }
        else if((cnt - 1) % 2 == 1){
            cout << "Johnson" << endl;
        }
        else cout << "Nancy" << endl;
    }
}

D. 挖沟

Solution

读题的时候注意一些关键字
由于需要在任意两个点之间传递信息,两个坑之间必须挖出至少一条通路, 希望挖出数量尽可能少的沟,使得任意两个据点之间有至少一条通路
显然就是求一个无向图最小生成树

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 + 5;

struct Edge {
  int u, v;
  ll w;
  bool operator < (const Edge &s) const {
    return w < s.w;
  }
}edge[N << 1];

int F[N], tot;
int findz(int x) {
  return F[x] = F[x] == x ? x : findz(F[x]);
}
void Union(int x, int y) {
  int fx = findz(x), fy = findz(y);
  if(fx != fy) {
    F[fx] = fy;
  }
}
ll Kruscal(int n) {
  ll ans = 0;
  for(int i = 1; i <= n; i++) F[i] = i;
  sort(edge, edge + tot);
  for(int i = 0; i < tot; i++) {
    int u = edge[i].u, v = edge[i].v;
    if(findz(u) != findz(v)) {
      Union(u, v);
      ans += edge[i].w;
    }
  }
  return ans;
}
int main() {
  ios::sync_with_stdio(false), cin.tie(nullptr);
  int n, m;
  cin >> n >> m;
  for(int i = 1; i <= m; i++) {
    int u, v;
    ll w;
    cin >> u >> v >> w;
    edge[tot].u = u, edge[tot].v = v, edge[tot].w = w;
    tot++;
  }
  cout << Kruscal(n) << "\n";
  return 0;
}

E. 签到题

Solution

看了题意后感觉是个珂朵莉树裸题(就是那个 序列操作)
然后就抄了个模板叫上去(区间赋 , 区间赋 )
最后查询区间 里面 的个数
然后 了, 不知道是什么原因(我题目理解错了
然后看了下大家的题解, 暴力就能做了
感觉还有线段树的做法, 但是好像跟珂朵莉树一样 了(那就写暴力吧)
update
我懂了, 不是区间赋值为 , 而是区间加(线段树搞搞就行)

Code1

#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define fi first
#define lc (x<<1)
#define se second
#define U unsigned
#define rc (x<<1|1)
#define Re register
#define LL long long
#define MP std::make_pair
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(Re int i = a;i <= b;++i)
#define ROF(i,a,b) for(Re int i = a;i >= b;--i)
#define SFOR(i,a,b,c) for(Re int i = a;i <= b;i+=c)
#define SROF(i,a,b,c) for(Re int i = a;i >= b;i-=c)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const int MAXN = 1000000+5;
int N,maxL;
std::set<std::pair<int,int> > L;
int vis[MAXN];
int main(){
     scanf("%d%d",&N,&maxL);
     int res=0;
     while(N--){
         int opt,x,y;
         scanf("%d%d%d",&opt,&x,&y);++x,++y;
         if(opt == 1){
             if(L.find(MP(x,y)) != L.end()) continue;
             L.insert(MP(x,y));
             for(int i=x;i<=y;++i){
                 ++vis[i];
                 res+=(vis[i]==1);
             }
         }
         if(opt == 2){
             if(L.find(MP(x,y)) == L.end()) continue;
             L.erase(MP(x,y));
             for(int i=x;i<=y;++i){
                 --vis[i];
                 res-=(vis[i]==0);
             }
         }
         if(opt == 3){
             printf("%d\n",res);
         }
     }
     return 0;
}

Code2(线段树)

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;

const int N = 1e6 + 5;
std::set < pair<int, int> > L;

struct node {
  int l, r;
  ll val;
  ll ans;
}t[N << 2];

void push_up(int rt) {
  if(t[rt].val) {
    t[rt].ans = t[rt].r - t[rt].l + 1;
  } else if(t[rt].l != t[rt].r) {
    t[rt].ans = t[rt << 1].ans + t[rt << 1 | 1].ans;
  } else {
    t[rt].ans = 0;
  }
}
void build(int rt, int l, int r) {
  t[rt].l = l, t[rt].r = r;
  if(l == r) {
    return ;
  }
  int mid = l + r >> 1;
  build(rt << 1, l, mid);
  build(rt << 1 | 1, mid + 1, r);
}
void update(int rt, int ql, int qr, int x) {
  if(t[rt].l >= ql && t[rt].r <= qr) {
    t[rt].val += x;
    push_up(rt);
    return ;
  }
  int mid = t[rt].l + t[rt].r >> 1;
  if(qr <= mid) {
    update(rt << 1, ql, qr, x);
  }
  else if(ql > mid) {
    update(rt << 1 | 1, ql, qr, x);
  }
  else {
    update(rt << 1, ql, mid, x);
    update(rt << 1 | 1, mid + 1, qr, x);
  }
  push_up(rt);
}
int main() {
  //ios::sync_with_stdio(false), cin.tie(nullptr);
  int m, n;
  cin >> m >> n;
  build(1, 1, n);
  while(m--) {  
    int op, l, r;
    cin >> op >> l >> r;
    if(op == 1) {
      if(L.find({l, r}) != L.end()) continue;
      L.insert({l, r});
      update(1, l, r, 1);
    }
    else if(op == 2) {
      if(L.find({l, r}) == L.end()) continue;
      L.erase({l, r});
      update(1, l, r, -1);
    }
    else {
      push_up(1);
      cout << t[1].ans << "\n";
    }
  }
}