周测题解

T1

此题是模拟,直接按照题目模拟即可(别被哈希吓到)

#include <iostream>
using namespace std;
int n, m, k, p[101], x, a[1000001];bool f; //f表示当前询问的位置有没有0
int main()
{
    cin >> n >> m >> k;
    for(int i = 0;i < k;++i)
        cin >> p[i];
    for(int i = 0;i < n;++i)
    {
        cin >> x;
        for(int j = 0;j < k;++j)
            a[x % p[j]] = 1; //按照公式计算
    }
    for(int i = 0;i < m;++i)
    {
        f = 0;
        cin >> x;
        for(int j = 0;j < k;++j)
            if(a[x % p[j]] == 0) //如果询问的位置是0
            {
                f = 1;break; //记录
            }
        if(f) cout << "yyhnb" << endl; //有0
        else cout << "yyhtql" << endl; //没有0,都是1
    }
    return 0;
}

T2

孟祥占公式,怎么推的未知

若 $s$ 为数组中所有数的和,$m$ 为数组中所有数的最大值

则有孟祥占公式:$ans=max(ceil(s/k),m)$

#include <iostream>
#include <cmath>
using namespace std;
double a[100001], n, m, s, k;
int main()
{
    cin >> n >> k;
    for(int i = 0;i < n;++i)
        cin >> a[i], m = max(m, a[i]), s += a[i];
    cout << max(int(ceil(s / k)), int(round(m)));
    return 0;
}

T3

前置知识: isdigit(char c),存在于cctype

作用等价于c >= '0' && c <= '9'


直接枚举每个位置,如果不是数字直接跳过

如果是数字,判断这个数字可不可以作为一个取件码的开头

注意要判断这个数字之前和整个取件码之后有没有别的数字

如果有,就会出现xxx-x-xxxx或者xx-x-xxxxx

所以这个数字之前和整个取件码之后如果有别的数字也不行

#include <iostream>
#include <string>
#include <cctype>
using namespace std;
string s = " ", t;bool b;
int main()
{
    while(cin >> t) s += t + ' ';
    for(int i = 1;i < s.length();++i)
    {
        if(/*前面没有数字*/!isdigit(s[i - 1]) && isdigit(s[i]) && isdigit(s[i + 1]) && s[i + 2] == '-' && isdigit(s[i + 3]) && s[i + 4] == '-' && isdigit(s[i + 5]) && isdigit(s[i + 6]) && isdigit(s[i + 7]) && isdigit(s[i + 8]) && /*后面没有数字*/!isdigit(s[i + 9]))
            cout << s.substr(i, 9) << endl, b = 1; //第一种取件码
        else if(/*前面没有数字*/!isdigit(s[i - 1]) && isdigit(s[i]) && s[i + 1] == '-' && isdigit(s[i + 2]) && s[i + 3] == '-' && isdigit(s[i + 4]) && isdigit(s[i + 5]) && isdigit(s[i + 6]) && isdigit(s[i + 7]) && /*后面没有数字*/!isdigit(s[i + 8]))
            cout << s.substr(i, 8) << endl, b = 1; //第二种取件码
    }
    if(!b) cout << -1;
    return 0;
}

T4

如果两个字符串没有重复,那么 $ans=a.length()×b.length()$

考虑什么时候会有重复的情况

只有a的前缀与b的后缀有重复时,才会有重复情况这不废话么

而且前缀和后缀的重复只会在前缀的末端和后缀的首端

而且前后缀都非空,

所以前缀的末端会在除a的首端以外的位置出现

后缀的首端会在除b的末端之外的位置出现

设所有重复部分都在集合 $s$ 中

根据模拟样例可知:

$ans=a.length()×b.length()-∑a.count(s_i)×b.count(s_i)$

代码实现

因为统计重复字串太难了复杂度较高,我们令 $s$ 中只有重复字符

$count$ 也不可能真正用 $a.count(),b.count()$,会 $TLE$

可以先把除a的首端以外的位置 $O(n)$ 地用计数排序思想统计一遍

再扫一遍除b的末端之外的位置,答案减去$tong[b[i]]$

#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
string a, b;unordered_map<char, int> tong;long long ans;
int main()
{
    cin >> a >> b;
    for(int i = 1;i < a.length();++i)
        ++tong[a[i]];
    ans = a.length() * b.length();
    for(int i = 0;i < b.length() - 1;++i)
        ans -= tong[b[i]];
    cout << ans;
    return 0;
}
posted @ 2021-07-17 19:15  5k_sync_closer  阅读(3)  评论(0编辑  收藏  举报  来源