A
题意:
给定n,输出一段长度为n的回文串。
大致思路:
判断n的奇偶来决定等于号的个数
void solve()
{
int n, m;
cin >> n;
if (n & 1)
{
m = n / 2;
for (int i = 1; i <= m; i++)cout << '-';
cout << '=';
for (int i = 1; i <= m; i++)cout << '-';
}
else
{
m = (n-2) / 2;
for (int i = 1; i <= m; i++)cout << '-';
cout << "==";
for (int i = 1; i <= m; i++)cout << '-';
}
}
B
题意:
判断是否存在不相同的两个数x,y。其中x>=3,y>=2。
大致思路:
遍历一遍记录他们的个数,在判断是否存在即可。
int flag[20], a, b;
void solve()
{
int x, n = 7;
while (n--)
{
cin >> x;
flag[x]++;
}
for (int i = 1; i <= 15; i++)
{
if (flag[i] >= 3)a++;
else if (flag[i] == 2)b++;
}
if (a&&a+b>=2)cout << "Yes";
else cout << "No";
}
C
题意:
判断是否有一个数数组中只出现一次,如果有或者有多个,输出最大的那个数的位置。
大致思路:
遍历一遍用map记录他们的个数。vector记录数和数的位置,再排序,从大的数开始判断。
int n;
vector<pair<int, int>>v;
map<int, int>mp;
void solve()
{
cin >> n;
int x;
for (int i = 1; i <= n; i++)
{
cin >> x;
v.emplace_back(x, i);
mp[x] += 1;
}
sort(v.begin(), v.end());
for (int i = n-1; i >= 0; i--)
{
if (mp[v[i].first] == 1)
{
cout << v[i].second << '\n';
return;
}
}
cout << -1;
}
D
题意:
位置(0,0)处有一个烟囱一直出烟,烟也会朝其他位置移动。给定人的位置,判断人是否会被烟覆盖。
大致思路:
每次来移动烟空间和时间花费都太多,所以只移动人和烟囱。
int n, xp, yp, xs, ys;
set<pair<int, int>>st;
string s;
int flag[200007];
void solve()
{
cin >> n >> xp >> yp;
cin >> s;
st.insert({ 0,0 });
for (int i = 0; i < s.size(); i++)
{
if (s[i] == 'N')
{
xp++;
xs++;
}
else if (s[i] == 'S')
{
xp--;
xs--;
}
else if (s[i] == 'E')
{
yp--;
ys--;
}
else if (s[i] == 'W')
{
yp++;
ys++;
}
st.insert({ xs,ys });
//printf("%d %d\n", xp, yp);
if (st.find({ xp,yp }) != st.end())flag[i] = 1;
}
for (int i = 0; i < n; i++)cout << flag[i];
}
E
题意:
和Takahashi比赛连边,每次连的边不能构成奇环。谁无法继续连边谁就输掉比赛。
大致思路:
暴力算出可以连多少个偶环,如果个数是奇数,则自己先手。反之Takahashi先手。
偶环用set存储,每一轮比赛删掉对应的即可。
vector<int>v[1007];
int n;
set<pair<int, int>>s;
void dfs(int from, int to,int cc,int st)
{
if (cc != 1 && cc % 2 == 1)
{
int x = to;
int y = st;
if (x > y)swap(x, y);
s.insert({ x,y });
}
for (int i = 0; i < v[to].size(); i++)
{
if (v[to][i] != from)dfs(to, v[to][i],cc+1,st);
}
}
void solve()
{
cin >> n;
int x, y, u, w;
for (int i = 1; i < n; i++)
{
cin >> x >> y;
v[x].emplace_back(y);
v[y].emplace_back(x);
}
for (int i = 1; i <= n; i++)
{
dfs(0, i,0,i);
}
if (s.size() % 2 == 1)
{
cout << "First" << endl;
x = (*s.begin()).first;
y= (*s.begin()).second;
cout << x << ' ' << y << endl;
s.erase({ x,y });
}
else cout << "Second" << endl;
while (1)
{
cin >> u >> w;
if (u == -1 && w == -1)return;
s.erase({ u,w });
x = (*s.begin()).first;
y = (*s.begin()).second;
cout << x << ' ' << y << endl;
s.erase({ x,y });
}
}
F
题意:
给定一个字符串s,找出以s为前缀的最短回文串。
大致思路:
要使回文串的长度减小,就要尽可能构造短的后缀。所以要找出字符串s中的最长回文串且该回文串是在字符串s的末尾。这样后缀只需要匹配字符串s那较短前缀就可以了。
找最长回文串直接套马拉车模板
string s,as;
char c;
int d[1000007], l, r, ans, ansl, ansr;
void solve()
{
cin >> as;
s = "!#";
for(int i=0;i<as.size();i++)
{
s.push_back(as[i]);
s.push_back('#');
}
s.push_back('@');
int len = s.size();
for (int i = 1; i < len; i++)
{
if (i < r)d[i] = min(d[l - i + r], r - i + 1);
while (s[i + d[i]] == s[i - d[i]])d[i]++;
d[i]--;
if (i + d[i] > r)r = i + d[i], l = i - d[i];
if (ans < r - l >> 1&&r==len-2)
{
ans = r - l >> 1;
ansl = l;
ansr = r;
}
}
cout << as;
for (int i = as.size() - ans - 1; i >= 0; i--)
{
cout << as[i];
}
}