The 2017 China Collegiate Programming Contest, Qinhuangdao Site

Contest Info


传送门

Solved A B C D E F G H I J K L M
9 / 13 O Ø O Ø O - O Ø - - - O O
  • O 在比赛中通过
  • Ø 赛后通过
  • ! 尝试了但是失败了
  • - 没有尝试

Solutions


A - Balloon Robot

题意:
\(n\)个人,\(m\)个座位组成一个圆环,\(1\leq n\leq 10^5,n\leq m\leq 10^9\)
现在有\(q,q\leq 10^5\)个事件,表示第\(i\)个人在\(t_i\)时刻A了一道题。
\(s_i\)表示每个人的位置。
现在有个机器人,可以选定他开始的位置,时刻从\(1\)开始。之后他会顺时针走,每一秒走一步。如果他在某一个位置时这个人目前已经A了题,他将会发放气球。
记一个人的怒气值为\(得到气球的时间-A题的时间\)
现在问起点选择哪个点使得所有人的怒气值之和最少。

思路:

  • 机器人起点肯定位于某个人的位置,所以起点一共有\(n\)个。
  • 每个事件对答案的贡献不会超过\(m\),其实可以将问题转化为一个模\(m\)意义下的问题。
  • 先求出机器人一开始位于\(1\)位置的答案。之后枚举每个可能的起点计算答案即可。
  • 机器人每移动一位所有事件的贡献在模意义下将减少\(1\),就相当于总答案减少\(p\)。那么枚举起点就可以\(O(1)\)转移答案了。

主要关键点在于将问题转化为模意义下的问题。
细节见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/18 16:22:01
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
int s[N];
int d[N];
void run() {
    int n,m,p; 
    cin >> n >> m >> p;
    for(int i=1; i<=n; i++) {
        cin >> s[i];
    }
    ll sum = 0;
    for(int i=0; i<p; i++) {
        int a,b; cin >> a >> b;
        d[i] = ((s[a] - b)%m + m) % m;
        sum += d[i];
    }
    ll ans = sum;
    sort(d,d+p);
    for(int i=0; i<p;) {
        int now=i;
        for(i++;i<p && d[i]==d[now]; i++);
        int cnt=i-now;
        ll res = sum - 1ll * p * d[now] + 1ll * now * m;
        ans = min(ans, res);
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T; while(T--)
    run();
    return 0;
}

B - Expected Waiting Time

题意:
先有\(n\)个面试者,有\(2n\)个时刻表示每个面试者到来的时间以及面试官选择面试的时间(顺序不确定)。
当等候室内的人数不小于\(1\)时,面试官能够选择某个时间随机挑选一个人进行面试,最后\(n\)个人都要面试完。
\(A\)为某个人到达的时间,\(S\)为面试官选择面试的事件,那么在任意一个时刻\(A\)的数量不小于\(S\)。显然有若干个合法的序列。最后求所有面试者等待的时间期望之和的平均值。

思路:
考虑对于任意一种合法的序列,期望之和为多少。显然此时和是不会改变的,不会因为面试官的选择而改变。那么面试官的随机选择我们可以看作一个固定选择,问题即转化为进出栈问题。
显然我们不可能枚举所有的情况,所以对于直接考虑一个位置为左括号、右括号的贡献,那么接下来我们只需要求出对应的情况数就行。接下来以右括号举例,左括号将序列翻转即可。
假设我们枚举到了位置\(j\),显然左边有个括号要与其匹配,我们枚举所有可能的位置\(j-1,j-3,j-5...\),从这些位置转移。那么中间的那些一定匹配成功,外面的那些也要匹配成功,所以就转化为了两个卡特兰数的乘积。即:

\[dp[j]=\sum_{i=j-1,i-=2}cat(\frac{i-j-1}{2})\cdot cat(\frac{n-(i-j+1)}{2}) \]

直接来求复杂度比较蛋疼。
注意到\(dp[j]=dp[j-2]+某一项\)。所以这样就可以\(O(n)\)枚举得到\(dp\)数组了。
接下来就很好办了,就按照刚刚的转化过程,逆着写得到期望之和就行。最后还要除以一个\(cat(n)\)
代码如下:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/20 16:34:50
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e6 + 5;

int n, MOD;
ll A, B, a[N], b[N];

int qpow(ll a, ll b) {
    ll res = 1;
    while (b) {
        if (b & 1) res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res;
}

int inv[N], cat[N];
void init(int n) {
    inv[0] = inv[1] = 1;
    for (int i = 2; i <= n + 1; i++) {
        inv[i] = 1ll * inv[MOD % i] * (MOD - MOD / i) % MOD;
    }
    cat[0] = cat[1] = 1;
    for (int i = 2; i <= n; i++) {
        cat[i] = 1ll * cat[i - 1] * (4 * i - 2) % MOD * inv[i + 1] % MOD;
    }
}

int dp[N];

void run() {
    cin >> n >> MOD >> b[0] >> A >> B;
    for (int i = 1; i <= 2 * n; i++) {
        b[i] = (1ll * A * b[i - 1] % MOD + B) % MOD;
        a[i] = (a[i - 1] + b[i] + 1) % MOD;
    }
    init(n);
    for (int i = 2; i <= 2 * n; i++) {
        dp[i] = (dp[i - 2] + 1ll * cat[i / 2 - 1] * cat[n - i / 2] % MOD) % MOD;
    }
    ll ans = 0;
    for (int i = 1; i <= 2 * n; i++) {
        if (i != 1) {
            ans = (ans + 1ll * a[i] * dp[i] % MOD) % MOD;
        }
        if (i != 2 * n) {
            ans = (ans - 1ll * a[i] * dp[2 * n - i + 1] % MOD) % MOD;
        }
    }
    ans = 1ll * ans * qpow(cat[n], MOD - 2) % MOD;
    if (ans < 0) ans += MOD;
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T; while(T--)
    run();
    return 0;
}

C - Crusaders Quest

签到。状压枚举所有情况即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/18 13:21:12
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
//#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

const char ss[] = {'g', 'a', 'o'};

void run() {
    string s; cin >> s;
    vector <int> p(3);
    iota(all(p), 0);
    int n;
    auto check3 = [&] (string&s, int i) {
        int j = i + 1, k = i + 2;
        if (k >= n) return false;
        return s[i] == s[j] && s[j] == s[k];
    };
    auto check2 = [&] (string&s, int i) {
        int j = i + 1;
        if (j >= n) return false;
        return s[i] == s[j];
    };
    int ans = 0;
    do {
        n = 9;
        int res = 0;
        string t = s;
        for (int k = 0; k < 3; k++) {
            int flag = 1;
            dbg(t, n);
            for (int i = 0; i < n; i++) if (t[i] == ss[p[k]]) {
                if (check3(t, i)) {
                    flag = 3;
                    break;
                } 
                if (check2(t, i)) {
                    flag = 2;
                    break;
                }
            }
            string tmp = "";
            dbg(flag);
            if (flag == 3) ++res;
            for (int i = 0; i < n; i++) {
                if (t[i] != ss[p[k]]) {
                    tmp += t[i];
                }
            }
            swap(t, tmp);       
            n = t.length();
        }
        dbg(res);
        ans = max(res, ans);
    } while (next_permutation(all(p)));
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T; while(T--)
    run();
    return 0;
}

D - Graph Generator

题意:
如果已知一个排列\(p\),第\(i\)次操作产生\(p_i\)。然后可以选定目前图中若干个连通块,将\(p_i\)与连通块中所有的点进行连边。
现在给定最后的图,问是否存在一个\(p\)和每次选择的集合,使得最终能够得到这个图。
\(n,m\leq 10^5\)

思路:
这种题从前往后很难构造,我们可以考虑从后往前在图中删点往前推。
观察到在一个连通块内,每次必然会先选择度数最大的点,因为当前选择的点要与其它所有点进行连边(注意是连通块)。
又有一个观察:每次去掉一个点后,其余所有的点度数都会减\(1\),也就是说度数的相对大小不变。
根据这两点做法呼之欲出了,我们只需要按照度数从大到小来处理。但现在还有个问题,连通块的问题,我们需要知道当前点所在连通块的size。
这种一般是并查集,但这里是删边,不好处理。所以。。直接上可撤销并查集就行了。先正着跑一遍,然后往前操作时不断从栈中取出之前状态进行还原。这样我们就能得到每一个时刻的连通状况。注意不能路径压缩,只能按秩合并。
细节见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/20 12:57:42
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
//#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

struct UFS {
    int f[N], h[N], sz[N], top;
    struct node {
        int x, y, fx, h, SZ;
    }sta[N];
    void init(int n) {
        top = 0;
        for (int i = 1; i <= n; i++) {
            sz[i] = 1;
            f[i] = i;
            h[i] = 0;
        }
    }
    int find(int x) {
        return f[x] == x ? f[x] : find(f[x]);
    }
    bool merge(int u, int v) {
        int x = find(u), y = find(v);
        if (x == y) return false;
        if (h[x] > h[y]) swap(x, y);
        sta[++top] = node{x, y, f[x], h[y], sz[y]};
        if (h[x] == h[y]) ++h[y];
        sz[y] += sz[x];
        f[x] = y;
        return true;
    }
    void undo(int k) {
        while (k--) {
            node it = sta[top--];
            f[it.x] = it.fx;
            h[it.y] = it.h;
            sz[it.y] = it.SZ;
        }
    }
    int query(int x) {
        int fx = find(x);
        return sz[fx];
    }
} ufs;

int n, m;
int d[N], a[N];
vector <int> G[N];
bool check[N];

void run() {
    cin >> n >> m;
    ufs.init(n);
    for (int i = 1; i <= n; i++) {
        d[i] = check[i] = 0;
        G[i].clear();
        a[i] = i;
    }
    for (int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v;
        ++d[u], ++d[v];
        G[u].push_back(v);
        G[v].push_back(u);
    }
    sort(a + 1, a + n + 1, [&](int i, int j) {
        if (d[i] == d[j]) return i < j;
        return d[i] < d[j];
    });
    vector <vector <int>> op(n + 1);
    for (int i = 1; i <= n; i++) {
        int u = a[i];
        for (auto v : G[u]) {
            if (d[v] <= d[u] && check[v]) {
                if (ufs.merge(u, v)) {
                    op[u].push_back(v);
                }
            }
        }
        check[u] = true;
    }
    vector <pair<int, vector<int>>> ans;
    for (int i = n; i >= 1; i--) {
        int u = a[i];
        int SZ = ufs.query(u);
        if (d[u] != SZ - 1) {
            cout << "No" << '\n';
            return;
        }
        ans.push_back(MP(u, op[u]));
        ufs.undo(sz(op[u]));
        for (auto v : G[u]) {
            --d[v];
        }
    }
    cout << "Yes" << '\n';
    reverse(all(ans));
    for (auto it : ans) {
        cout << it.fi << ' ' << sz(it.se);
        for (auto it2 : it.se) {
            cout << ' ' << it2;
        }
        cout << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T; while(T--)
    run();
    return 0;
}

E - String of CCPC

签到。答案最多增加\(1\),随便乱搞即可。

Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
const int MAXN = 2e5 + 5, MAXM = 4e5 + 5, BOUND = 2e5, MOD = 1e9+7, INF = 0x3f3f3f3f, base = 10000;
const int inv2 = (MOD + 1) >> 1;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0), eps = 1e-9;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define lc(x) ch[x][0]
#define pii pair<int,int>
#define vi vector<int>
#define vii vector<pair<int,int>>
#define rc(x) ch[x][1]
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define all(a) (a).begin(), (a).end()
#define sz(a) int(a.size())
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fi first
#define se second
#define MP std::make_pair
#define ri register int
//#define sz(a) int((a).size())
inline int add(int a, int b) {return a + b >= MOD ? a + b - MOD : a + b;}
inline int dec(int a, int b) {return a < b ? a - b + MOD : a - b;}
inline int mul(int a, int b) {return 1ll * a * b % MOD;}
template <typename T>
inline void cmin(T &a,T b){a = min(a,b);}
template <typename T>
inline void cmax(T &a,T b){a = max(a,b);}
ll qpow(ll a,ll b){
    ll ans=1;
    for(;b;b>>=1,a=a*a%MOD)if(b&1)ans=ans*a%MOD;
    return ans;
}
mt19937 mrand(random_device{}());
char s[MAXN];
int mp[5][2] = {{1,0},{2,0},{2,3},{4,0},{2,0}};
void run(){
    int n;cin>>n;
    cin>>(s+1);
    int ans=0,sta=0;
    bool flag=false;
    rep(i,1,n){
        if(sta==2 && s[i]=='C'){
            if(!flag){
                flag=true;
                ans++;
            }
        }
        if(sta==1 && s[i]=='P' && i+1<=n && s[i+1]=='C'){
            if(!flag){
                flag=true;
                ans++;
                //cout<<"lalala\n";
            }
        }
        if(s[i]=='C'){
            sta = mp[sta][0];
        }else if(s[i]=='P'){
            sta = mp[sta][1];
        }
        if(sta==4)ans++;
        if(i==n && sta==3){
            if(!flag){
                flag=true;
                ans++;
            }
        }
        //cout<<sta<<" \n"[i==n];
        //cout<<ans<<" \n"[i==n];
    }
    cout<<ans<<'\n';
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int _;cin>>_;
    while(_--)run();
    return 0;
}

G - Numbers

二进制位从高到低贪心即可。涉及到大数,所以用的python。

Code
t = int(input())
for i in range(t):
    n, m = map(int, input().split())
    pw = []
    i = 1
    while i <= n:
        pw.append(i)
        i *= 2
    ans = 0
    mx = 0
    for i in range(len(pw)-1, -1, -1):
        if mx + m*(pw[i]-1) < n:
            ans += pw[i]
            mx += min(m, (n-mx)//pw[i])*pw[i]
        #print(pw[i], mx)
    print(ans)

H - Prime Set

题意:
定义一个素数集为\(\{i,j\}\)并且\(a_i+a_j\)为素数。
给定序列\(a\),现从中选择至多\(k\)个素数集,使得并起来的元素个数最多。
\(n\leq 10^3,0\leq k\leq \frac{n\cdot(n-1)}{2}\)

思路:
利用“两个数加起来为素数”这个条件,我们容易发现除开\(1+1=2\)这种情况,其余都是一奇一偶。这有点二分图的意思。
所以考虑建二分图,奇数在左边,偶数在右边,然后按照题意要求进行连边求个最大匹配即可。
注意\(1\)的存在比较特殊,应该最后再从\(1\)出发跑增广路。这样答案能够更优。
最后再\((1,1)\)进行匹配。
细节见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/18 19:30:23
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e6 + 5;

int v[N], prime[N];
int num;
void init() {
    for(int i = 2; i < N; i++) {
        if(v[i] == 0) {
            v[i] = i;
            prime[++num] = i;
        }
        for(int j = 1; j <= num && prime[j] * i < N; j++) {
            v[prime[j] * i] = prime[j] ;
        }
    }
} 

int n, k;
int a[N];
int Match[N];

struct MaxMatch {
    int n;
    vector<int> G[N];
    int vis[N], left[N], clk;

    void init(int n) {
        this->n = n;
        for (int i = 1; i <= n; i++) G[i].clear();
        fill(vis + 1, vis + n + 1, -1);
    }
    
    void adde(int u, int v) {
        G[u].push_back(v);
        G[v].push_back(u);
    }
    
    bool dfs(int u) {
        for (int v: G[u])
            if (vis[v] != clk) {
                vis[v] = clk;
                if (Match[v] == -1 || dfs(Match[v])) {
                    Match[u] = v;
                    Match[v] = u;
                    return true;
                }
            }
        return false;
    }

    int solve() {
        int res = 0;
        for (int i = 1; i <= n; i++) {
            if ((a[i] & 1) && a[i] > 1) {
                ++clk;
                res += dfs(i);
            }
        }
        for (int i = 1; i <= n; i++) {
            if (a[i] == 1) {
                ++clk;
                res += dfs(i);
            }
        }
        int x = 0;
        for (int i = 1; i <= n; i++) {
            if (a[i] == 1 && Match[i] < 0) {
                ++x;
                Match[i] = 0;
            }
        }
        return res + x / 2;
    }
    
} MM;

void run() {
    cin >> n >> k;
    MM.init(n);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        Match[i] = -2;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            if (v[a[i] + a[j]] == a[i] + a[j]) {
                Match[i] = Match[j] = -1;
                if (a[i] == 1 && a[j] == 1) continue;
                MM.adde(i, j);
            }
        }
    }
    int t = MM.solve();
    if (t < k) {
        int noMat = 0;
        for (int i = 1; i <= n; i++) {
            if (Match[i] == -2) {
                ++noMat;
            }
        }
        int r = n - 2 * t - noMat;
        cout << 2 * t + min(r, k - t) << '\n';
    } else {
        cout << 2 * k << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    init();
    int T; cin >> T; while(T--)
    run();
    return 0;
}

L - One-Dimensional Maze

签到。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/18 13:08:04
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

void run() {
    int n, m; cin >> n >> m; --m;
    string s; cin >> s;
    vector <int> sum(n);
    sum[0] = (s[0] == 'L');
    for (int i = 1; i < n; i++) {
        sum[i] = sum[i - 1] + (s[i] == 'L');
    }
    int ans = min(m + 1 - sum[m] - (s[0] == 'R'), sum[n - 2] - sum[m - 1]);
    ans = max(ans, 0);
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T; while(T--)
    run();
    return 0;
}
posted @ 2020-06-20 21:34  heyuhhh  阅读(273)  评论(0编辑  收藏  举报