[2019藍橋杯國賽B組c++][最優包含][排列數][第八大奇蹟]

xxb3.1415發表於2020-11-12

個人題解連結,藍橋杯歷屆試題,正在更新中~

最優包含

題目連結:點選
思路:顯然的dp.
設 狀 態 為 d p [ i ] [ j ] 代 表 前 i 個 包 含 前 j 個 要 改 變 的 次 數 設狀態為dp[i][j] 代表前i個包含前j個要改變的次數 dp[i][j]ij
轉移方程:
i f s [ i ] = = t [ j ] : d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] if s[i]==t[j] :dp[i][j]=dp[i-1][j-1] ifs[i]==t[j]:dp[i][j]=dp[i1][j1]
e l s e : d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − 1 ] + 1 ) else:dp[i][j]=min(dp[i-1][j],dp[i-1][j-1]+1) else:dp[i][j]=min(dp[i1][j],dp[i1][j1]+1)
注意初始化為正無窮, d p [ i ] [ 0 ] dp[i][0] dp[i][0]初始化為0

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double Pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i <  (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define _srep(n,m,i)for (register int i = (n); i >= (m); i--)
#define _sfor(n,m,i)for (register int i = (n); i >  (m); i--)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 1e3+5;
char s[N], t[N];
int dp[N][N];// 前i個和包括了前j個要改幾次 
int main() {
  scanf("%s %s", s + 1, t + 1);
  int n = strlen(s+1), m = strlen(t+1);
  memset(dp, 0x3f, sizeof dp);
  
  dp[0][0] = 0;
  
  for(int i = 1; i <= n; ++i) {
    dp[i][0] = 0;
    for(int j = 1; j <= m && j <= i; ++j) {
      if(s[i] == t[j]) {
        dp[i][j] = dp[i-1][j-1];
      } else {
          dp[i][j] = min(dp[i-1][j], dp[i-1][j-1] + 1);
      }
    }
  }
  cout << dp[n][m] << endl;
}

排列數

題目連結:排列數
思路:顯然dp
設 狀 態 為 d p [ i ] [ j ] 代 表 前 i 個 數 , 有 j 個 折 點 設狀態為dp[i][j]代表前i個數,有j個折點 dp[i][j]ij
我們可以發現折點的數量就是波峰+波谷的數量。
雖然推出來後轉移方程很簡單,但是並不是特別的好推,我們得先把各種情況先看一遍,最後總結起來你就會發現轉移很簡單。
對於不同的折點數量,我們分為奇數偶數考慮,再對於每種情況我們分最後一個是波峰還是波谷考慮。
然後對於i個數,要變成i+1個數,肯定是插入了i+1,然後它有i+1個位置可以選擇。我們發現波峰周圍的2個位置是特殊的,在這裡插入,折點的數量不變。如果最後一個是波谷,那麼在最後插入會不變,如果第一個也是波谷,那麼在第一個位置插入也會不變(分成奇偶,和最後一個是波峰波谷就可以判斷出這兩種情況)。最後總結起來就是
d p [ i + 1 ] [ j ] + = d p [ i ] [ j ] ∗ 2 dp[i+1][j]+=dp[i][j]*2 dp[i+1][j]+=dp[i][j]2
d p [ i + 1 ] [ j + 1 ] = d p [ i ] [ j ] ∗ ( j + 1 ) dp[i+1][j+1]=dp[i][j]*(j+1) dp[i+1][j+1]=dp[i][j](j+1)
d p [ i + 1 ] [ j + 2 ] = d p [ i ] [ j ] ∗ ( i + 1 − j − 1 − 2 ) dp[i+1][j+2]=dp[i][j]*(i+1-j-1-2) dp[i+1][j+2]=dp[i][j](i+1j12)
答案就是 d p [ n ] [ k − 1 ] dp[n][k-1] dp[n][k1]

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double Pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i <  (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define _srep(n,m,i)for (register int i = (n); i >= (m); i--)
#define _sfor(n,m,i)for (register int i = (n); i >  (m); i--)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int Mod = 123456;
const int N = 5e2+5;
int dp[N][N] ;
int main() {
  int n, k; read(n); read(k);
  dp[1][0] = 1;
  for(int i = 2;  i <= n; ++i) {
    dp[i][0] = 2;
    for(int j = 0; j <= i - 2; ++j) {
      dp[i][j] %= Mod;
      dp[i+1][j] += dp[i][j] * (j+1);
      dp[i+1][j+1] += dp[i][j] * 2;
      dp[i+1][j+2] += dp[i][j] * (i-j-2);
    }
  }
  cout << dp[n][k-1] % Mod << endl;
} 

第八大奇蹟

題目連結:點選
思路:這題其實就是一道裸題,整體二分or樹套樹,當然用整體二分好寫點。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double Pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i <  (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define _srep(n,m,i)for (register int i = (n); i >= (m); i--)
#define _sfor(n,m,i)for (register int i = (n); i >  (m); i--)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 1e5+5;
int a[N];
struct node {
  int op, x, y, k, id;
}e[N*10], lq[N], rq[N];
int cnt, ans[N];
int T[N];
int n, L;
void upd(int pos, int val) {
  for(; pos <= L; pos += lowbit(pos)) T[pos] += val;
}
int qry(int pos) {
  int res = 0;
  for(; pos; pos -= lowbit(pos)) res += T[pos];
  return res;
}
void solve(int vl, int vr, int ql, int qr) {
  if(ql > qr || vl > vr) return ;
  if(vl == vr) {
    for(int i = ql; i <= qr; ++i) {
      if(e[i].op == 2) ans[e[i].id] = vl;
    }
    return ;
  }
  int mid = vl + vr >> 1, l = 0, r = 0;
  for(int i = ql; i <= qr; ++i) {
    if(e[i].op == 1) {
      if(e[i].y > mid) {
        upd(e[i].x, e[i].k);
        rq[++r] = e[i];
      } else {
        lq[++l] = e[i];
      }
    } else {
      int k = qry(e[i].y) - qry(e[i].x-1);
      if(k < e[i].k) {
        e[i].k -= k;
        lq[++l] = e[i];        
      } else {
        rq[++r] = e[i];
      }
    }
  }
  for(int i = ql; i <= qr; ++i) {
    if(e[i].op == 1 && e[i].y > mid) {
      upd(e[i].x, -e[i].k);
    }
  }
  for(int i = 1; i <= l; ++i) e[i+ql-1] =  lq[i];
  for(int i = 1; i <= r; ++i) e[i+ql+l-1] = rq[i];
  solve(vl, mid, ql, ql+l-1);
  solve(mid+1, vr, ql+l, qr);
  
}
int main() {
  read(L); read(n);
  char op[3];
  memset(ans, -1, sizeof ans);
  for(int i = 1, x, y; i <= n; i++) {
    scanf("%s %d %d", op, &x, &y);
    if(op[0] == 'C') {
      if(a[x]) {
        e[++cnt] = node {1, x, a[x], -1};
        e[++cnt] = node {1, x, y, 1};
        a[x] = y;
      } else {
        e[++cnt] = node {1, x, y, 1};
        a[x] = y;
      }
    } else {
      e[++cnt] = node {2, x, y, 8, i};
    }
  }
  solve(0, 1e9, 1, cnt);
  for(int i = 1; i <= n; ++i) {
    if(~ans[i]) {
      printf("%d\n", ans[i]);
    }
  }
}

相關文章