周测题解
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;
}