A ~ C
先声明,本人不是什么大佬,写这些题解只是面向刚打比赛的朋友,若题解存在问题,敬请指正!
A- 冰冰的正多边形
A题可能会不太理解自己错在哪里,题目要求解可以构成的多边形中最小周长,我们用map记录棒子的长度以及拥有的数量,然后遍历map,如果长度为 X 的木棒数量 >= 3,就记录一下答案,ans = min ( ans, X * 3 ),注意这里不是乘它的数量而是乘 3,因为题目要的是最小的周长,我们构造一个正三角形就够了
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int t, n, m;
void solve()
{
cin>>n;
map<int,int>mp;
for(int i=0;i<n;i++)
{
int x;
cin>>x;
mp[x]++;
}
bool sign=0;
int ans=1000000;
for(auto it:mp)
{
if(it.second>=3)
{
sign=1;
ans=min(ans,it.first);
}
}
if(sign)
{
cout<<"yes"<<endl;
cout<<ans*3<<endl;
}
else
cout<<"no"<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
t = 1;
cin>>t;
while (t--)
{
solve();
}
return 0;
}
B-冰冰的电子邮箱
B题模拟,需要充分考虑字符的范围(字母 或 数字 或 ' . ' 或 ' - ' )以及字符长度。
算长度的时候要是不太清楚要不要-1或者要不要取等,就自己举个例子吧,比如假设 index = 60 字符串长度为 65,也就是说下标最后会来到 65 的位置,那么 ' @ ' 后面的字符串长度就是 61 ~ 64 总共 4 个字符,也就是 i - index - 1,不能超过 255 ,也就是说如果 i - index -1 > 255 就输出 " no "
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int t, n, m;
void solve()
{
string s;
cin>>s;
int index=s.find('@');
if(index==-1 || index==0 || index==s.size()-1 || index>64)//这里已经判断了前半部分的字符串长度
{
cout<<"No"<<endl;
return;
}
if(s[0]=='.' || s[index-1]=='.' || s[index+1]=='.' || s[s.size()-1]=='.' || s[index+1]=='-' || s[s.size()-1]=='-')
{
cout<<"No"<<endl;
return;
}
int i=0;
for(i=0;i<index;i++)
{
if(!((s[i]>='a'&&s[i]<='z') || (s[i]>='A'&&s[i]<='Z') || (s[i]>='0'&&s[i]<='9') || s[i]=='.'))
{
cout<<"No"<<endl;
return;
}
}
for(i=index+1;i<s.size();i++)
{
if(!((s[i]>='a'&&s[i]<='z') || (s[i]>='A'&&s[i]<='Z') || (s[i]>='0'&&s[i]<='9') || s[i]=='.' || s[i]=='-'))
{
cout<<"No"<<endl;
return;
}
}
if(i-index-1>255)
{
cout<<"No"<<endl;
return;
}
cout<<"Yes"<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
t = 1;
cin>>t;
while (t--)
{
solve();
}
return 0;
}
C-冰冰的异或
C题是找规律,但是我们首先要理解MEX,这个概念挺重要的,对于其他的MEX题目也通用。
给定一个序列 [ 1, 3, 2, 0, 5, 6 ],对它从小到大排序后是这样的 [ 0, 1, 2, 3, 5, 6 ],会发现这个排列少了4,那么这个序列的 MEX 就是4;再比如 [ 3, 1, 2 ],排完序是 [ 1, 2, 3 ],MEX 就是0。MEX就是从 0 开始,第一个没有在序列里出现的元素
好,再来讲一下异或 ⊕ ,异或就是将一个十进制的数转换为二进制,从右往左按照相同为0,不同为1的规则运算得到一个新的数,首先异或满足交换律,就是 a ⊕ b = b ⊕ a,还有 a ⊕ a = 0,所以我们选取两个数的时候不用考虑(i,j)、(j,i),这两种情况是一样的结果。
我们找几个例子来找规律
- n = 1,那只能取 1 了,而 1 ⊕ 1 = 0,从0开始,第一个没有出现的数是 1,所以MEX = 1;
- n = 2,我们可以取(1, 1), (1, 2), (2, 2), (2, 1),但是因为 a ⊕ a = 0,以及 a ⊕ b = b ⊕ a,所以只有(1, 1), (1, 2) 这两种结果(当然你可以取其他组合,但结果只有两个),1 ⊕ 2 = 3,1 ⊕ 1 = 0 (这个结果你们可以在草稿纸上算出来,计算时心里默念:相同为0,不同为1,相同为0,不同为1...不容易懵圈),所以MEX = 1;
- n = 3,我们可以在 n = 2 的基础上取 (1, 3), (2, 3),1 ⊕ 3 = 2, 2 ⊕ 3 = 1,现在我们有了 0, 1, 2, 3(3是 n = 2 时 (1, 2): 1 ⊕ 2 的结果, 所以 MEX = 4;
依次列举 n = 4, 5, 6, 7, 8,你会发现,n = 4, MEX = 4; n = 5, n = 6, n = 7, n = 8, MEX都等于 8,也就是说 1 ~ 8的数的任意组合的异或都不会得到 8 ,但是 n = 9 的时候,1 ⊕ 9 = 8,好,我们有 8 了,我们就去尝试 n = 9 ~ 16能不能得到9 ~ 15这些数,发现都可以得到,但怎么都得不到 16, 只有 n = 17时,1 ⊕ 17 = 16,把1 ⊕ 3 = 2, 1 ⊕ 5 = 4, 1 ⊕ 9 = 8, 1 ⊕ 17 = 16,这些式子放在一起,我们发现 MEX 都会卡在 2的幂次方的地方,而且当 n > 2^x 时,1 ⊕ n 就会得到 2^x,这样就会解锁MEX,MEX翻倍,这样我们就找到规律了
另外 n = 1, 2 时要特判一下
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL t, n, m;
void solve()
{
cin>>n;
if(n<3)
{
cout<<1<<endl;
return;
}
LL temp=1;
while(1)
{
temp*=2;
if(temp>=n)
{
cout<<temp<<endl;
return;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
t = 1;
cin>>t;
while (t--)
{
solve();
}
return 0;
}