本次比赛,a,f,i三道题为签到题,直接做就行,其他题模拟的较多,本篇文章将着重补G,J,D,三题
A 国际旅行 Ⅰ
由于国家联通,我们只需要将国家按照城市的数量从小到大排序,输出相应城市数量即可。
F 水灵灵的小学弟
一般的博弈题相对较难,但这道题两人名字首字母大写相同,所以直接输出DHY即可。
I I:重生之zbk要拿回属于他的一切
这题的数据范围小,我们直接用暴力,遍历字符串,查找chuan的数量
for (int i = 0; i <= s.length()-5; i++) {
string b=s.substr(i, 5);
if (b == "chuan") {
count++;
}
}//记得对i长度特判,
D A*BBBB
首先我们发现数据范围太大,不能直接乘,但是根据题目中所说b每一位都相同,我们可以进行模拟.
例如a=1234,b=2222;
另a*2=2 4 6 8 ;用前缀和进行计算
最后的结果使用2468+24680+246800+246800得出的结论也就是说,b有多少位,最后我们就要迁移多少次。
因为我们用的是字符型,所以在计算前先将字符倒置,最后要记得去除前导0。
void solve(){
memset(a,0,sizeof(a));
string A,B;
cin >> A >> B;
reverse(A.begin(),A.end());//倒置字符串
int len = A.size();
for(int i = 0; i < len; i++){
a[i] = A[i] - '0';
a[i] *= (B[0]-'0');
}//将字符串转化为数组,与b各位相乘
for(int i = 0; i < len; i++){
if(a[i] >= 10) {
a[i + 1] += a[i] / 10;
a[i] %= 10;
}//利用前缀和进行维护,进位
}
if(a[len] == 0) len--;//去除前导0
reverse(a,a + len + 1);//还原
int lenb = B.size();//计算b的位数,进行迁移相加
ans[0] = a[0];
for(int i = 1; i <= len; i++){
ans[i] = ans[i - 1] + a[i];
}
int r = -1,l = -lenb-1;
int anslen = len + lenb -1;
for(int i = 0; i <= anslen; i++){
r ++, l ++;
int rr ,ll;
if(r > len) rr = ans[len];
else rr = ans[r];
if(l < 0) ll = 0;
else ll = ans[l];
res[i] = rr - ll;
}
for(int i = anslen; i >= 1; i--){
if(res[i] >= 10) {
res[i - 1] += res[i] / 10;
res[i] %= 10;
}
}//再次进行维护
int zero = 0;
for(int i = 0; i <= anslen;i++){
if(res[i] == 0 && zero == 0 && i != anslen) continue;
zero = 1;
cout << res[i];
}
cout << endl;
return ;
}
G 狼狼的备忘录
模拟题,题目较长,理解题意
用map来映射队员的名字,其中嵌套有set,自动排序。在处理星座信息时,我们进行去重操作,将多余信息去除。最后将队员姓名按字典顺序排序输出信息。
在去重操作中,因为数据范围小,可以直接用暴力。
void solve(){
int n;cin >> n;
map<string,set<string>> m;
for(int i=0;i<n;++i){
string s;int q;
cin >> s >> q;
while(q--){
string x;cin >> x;
if(m[s].empty()) m[s].insert(x);
else{
int flag=1;
vector<string> r;
for(auto t : m[s]){
if(t.size()>=x.size()){
int k=t.rfind(x);
if(k!=-1){
if(k+x.size()==t.size()) flag=0;
}
}
else{
int k=x.rfind(t);
if(k!=-1){
if(k+t.size()==x.size()) r.push_back(t);
}
}
}
if(flag) m[s].insert(x);
if(!r.empty()){
for(auto c : r) m[s].erase(c);
}
}
}
}
cout << m.size() << endl;
for(auto i : m){
cout << i.fi << " " << i.se.size() << " ";
for(auto j : i.se){
cout << j << " ";
}
cout << endl;
}
return ;
}
J 这是签到
在比赛的时候,如果实在没有思路,这个题直接暴力。因为他n,m<=5,所以直接把五以内的式子列出来。
此外,我们要了解全排列函数,以便于简化代码
next_permutation
int minn = min(n,m);
for(int i = 1; i <= minn; i++){
int res = 0;
int len = 1;
for(int j = 1; j <= i; j++){
len *= j;
}
int a[i + 1];
for(int j = 1; j <= i; j++) a[j] = j;
for(int j = 1; j <= len; j++){
int aa = 1;
int N = 0;
for(int x = 1; x <= i; x++){
for(int z = x + 1; z <= i; z++){
if(a[z] < a[x]) N++;
}
}
for(int x = 1; x <= i; x++){
aa *= arr[x][a[x]];
}
next_permutation(a + 1,a + 1 + i);
if(N & 1){
res -= aa;
} else{
res += aa;
}
}
if(res <= maxx) maxx = res;
}
cout << maxx << endl;
return ;
}