省赛选拔

65 阅读1分钟

E F

在你的帮助下,牛小轩熟练掌握了数据破解的基本操作,并成为了牛博士的得力助手。明天就要进行密码破译课程的阶段性测试,但是今天牛博士家里有事,所以拜托你帮忙验一下明天的测验题——给出一个密码串s,需要根据对应的解码规则输出新的串。解码规则为对于给定的密码串s,给出一个解码串t,如果在s中出现t则将t从密码串中拿掉,同时合并分裂的两串,之后一直重复此过程,直到串s中没有t,请输出解码后的串s。你发现和之前牛小轩给你的题目一样,唯一不同的是这次的解码串太长了,好像不能用上次的解法。

思路:类似于栈,每进一位进行比较,这里主要是判断是不是匹配花时间,所以我们可以用字符串哈希来进行比较 这里我怕他卡我,所以用了双哈希

代码:

#include <bits/stdc++.h>
// #define int long long
using namespace std;
const int base1 = 101,p = 9999971,base2 = 131,p1 = 9999973 ;
char a[2000011],b[2000011];
int ha[2000011],c[2000011],c1[2000011],ha1[2000001];
vector<int>hb,hb1;

void hash1(int n,int m)
{
    c[0] = 1;
    c1[0] = 1;
    for(int i = 1;i <= 2000000; i ++)
    {
        c[i] = c[i - 1] * base1 %p;
        c1[i] = c1[i - 1] * base2 % p1;
    }
    int res = 0;
    for(int i = 1;i <= n;i ++)
    {
        ha[i] = (ha[i - 1] * base1 + a[i] - 'a' + 1 ) % p;
        ha1[i] = (ha1[i - 1] * base2 + a[i] - 'a' + 1) % p1;
    }
}
bool check(int u,int w,int k)
{
    int l = (hb.back()*base1 + b[u] - 'a' + 1)%p;
    int r = (hb1.back()*base2 + b[u] - 'a' + 1)%p1;
    hb.push_back(l),hb1.push_back(r);
    if(k < w)
        return false;
    int res = (hb.back()- 1LL * hb[hb.size()-w-1] * c[w] % p + p ) % p;
    int pos = (hb1.back() - 1LL * hb1[hb.size()-w-1] * c1[w] % p1 + p1)%p1;
    if(res== (ha[w])&& pos == (ha1[w]))
    {
        while(w--)
        {
            hb.pop_back();
            hb1.pop_back();
        }
        return true;
    }
    return false;

}
int main()
{
    string s,t;
    cin >> s >> t;
    for(int i = 0;i < t.size();i ++)
        a[i+1] = t[i];
     for(int i = 0;i < s.size();i ++)
        b[i+1] = s[i];
    hash1(t.size(),s.size());
    hb.push_back(0),hb1.push_back(0);
    vector<int>q;
    //cout << t.size()<< '\n';
    for(int i = 1;i <= s.size();i ++)
    {
//         q.push_back(i);
        bool f = false;
        
        if(check(i,t.size(),q.size()+1))
        {
            int x = t.size()-1;
            while(x--)
            q.pop_back();
            f = true;
        }
        if(!f)
            q.push_back(i);
    }
    for(int i = 0;i < q.size();i ++)
        cout << b[q[i]];
    cout << '\n';
}

G

牛牛大学是专门培养acmer的学校,每一个来这里的学生都有一个分数,代表他们的初始能力值,今天是牛牛大学第一届招生,一共招收了n名同学,他们各自的能力值用ai表示,刚刚步入大学,首先面临的就是分班问题,牛牛校长想把n名同学分成两个班(题目保证n为偶数),并且让这两个班级的能力值尽可能平均,即分完班之后两个班级能力值中位数相差最少,请你帮忙算算两个班能力值中位数相差最少是多少。

思路:这里其实是题目有问题没有说清楚,很多人都卡在 1 2 3 4 5 6 7 8 这个样例,这其实就是一道规律题

就是排序后的中间两数相减

代码:

void solve()
{
    int n;
    cin >> n;
    vector<int> a(n +1);
    for(int i = 1; i <= n; i ++) cin >> a[i];
    sort(a.begin() +1,a.end());
    //for(int i = 0; i < n; i ++) cout << a[i] << " ";
    cout << a[n/2+1] - a[n/2] << endl;
}