A. Subtle Substring Subtraction
给你一个字符串,Alice先手并取偶数长度的子串,Bob后手并取奇数长度的子串,问取完整个字符串谁的值最大,差值是多少
易知Alice一定会取最长的偶数子串,先特判一下字符串长度为1时Bob赢
然后如果是偶数长度就直接取完,否则判断一下第一个字符和最后一个字符谁大,留一个小的给Bob剩下的全部取完就行
/****************
*@description:for the Escape Project
*@author: Nebula_xuan
* @Date: 2022-04-30 22:39:31
*************************************************************************/
#include <iostream>
using namespace std;
const int N = 2e5 + 10;
int main()
{
int t;
cin >> t;
while (t--)
{
string a;
cin >> a;
if (a.size() == 1)
{
cout << "Bob ";
cout << a[0] - 'a' + 1;
}
else
{
cout << "Alice ";
long long sum = 0;
if (a.size() % 2)
{
if (a[0] > a[a.size() - 1])
{
for (int i = 0; i < a.size() - 1; i++)
sum += a[i] - 'a' + 1;
sum -= a[a.size() - 1] - 'a' + 1;
}
else
{
for (int i = 1; i < a.size(); i++)
sum += a[i] - 'a' + 1;
sum -= a[0] - 'a' + 1;
}
}
else
{
for (int i = 0; i < a.size(); i++)
sum += a[i] - 'a' + 1;
}
cout << sum;
}
puts("");
}
}
B. A Perfectly Balanced String?
定义一个字符串是完美的当所有子串任意两个字符出现的次数差值不超过1
询问每个字符串是否完美
首先存储一下字符串中出现了几种字符,然后查找两个相同字符的差值是否>=字符的种类,如果没有则直接输出NO(即一定存在某个字符没有出现在两个相同字符形成的子串中,0和2差值大于1),判断完整个循环没有输出NO即输出YES
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int f[27];
int main()
{
int t;
cin >> t;
while (t--)
{
set<int> s;
for (int i = 0; i <= 26; i++)
f[i] = -1;
string str;
cin >> str;
for (int i = 0; i < str.size(); i++)
s.insert(str[i] - 'a');
bool flag = true;
for (int i = 0; i < str.size(); i++)
{
if (f[str[i] - 'a'] != -1)
{
if ( i - f[str[i]-'a'] + 1 < s.size())
{
flag = false;
break;
}
}
f[str[i] - 'a'] = i + 1;
}
if (flag)
puts("YES");
else
puts("NO");
}
}
C. Palindrome Basis
给你一个数,问你它被分成若干回文数之和的方案数
先预处理出前4e4中有多少回文数,然后就是用完全背包的板子
假设当前数为
x
x
x ,我们本次取的回文数为
y
y
y
那么
f
[
x
]
+
=
f
[
x
−
y
]
;
f[x]+=f[x-y];
f[x]+=f[x−y];
记得初始化
f
[
0
]
=
1
f[0]=1
f[0]=1
#include <cstring>
#include <iostream>
using namespace std;
const int N = 4e4 + 10;
int f[N], s[N];
bool vis[N];
const int mod = 1e9 + 7;
bool solve(int x)
{
unsigned i = x;
unsigned m = 0;
while (i > 0)
{
m = m * 10 + i % 10;
i /= 10;
}
return m == x;
}
int main()
{
int t;
cin >> t;
vis[0] = true;
int cnt = 0;
for (int i = 1; i <= 4e4; i++)
{
if (solve(i))
f[++cnt] = i;
}
s[0] = 1;
for (int i = 1; i <= cnt; i++)
{
for (int j = f[i]; j <= 40005; j++)
{
s[j] = (s[j] + s[j - f[i]]) % mod;
}
}
while (t--)
{
int n;
cin >> n;
cout << s[n] << endl;
}
}
D. Lost Arithmetic Progression
给你三个等差数列,其中A数列与B数列的交集为C数列
告诉你B数列和C数列,问你A数列都多少种情况
首先我们分情况讨论
①不存在A数列的可能:
很容易想到如果两个数列的公差(设B数列公差为
q
q
q,首项为
b
b
b,C数列公差为
r
r
r,首项为
c
c
c 显然q<=r)如果C的公差不是B的公差的倍数,即
r
%
q
!
=
0
r\%q!=0
r%q!=0那么不可能存在
其次就是两个数列的“相对位移”,即
(
c
−
b
)
%
q
!
=
0
(c-b)\%q!=0
(c−b)%q!=0那么就是“错位”同样不可能存在
最后就是如果B数列的最后一项小于C数列的第一项或者C数列的最后一项小于B数列的第一项,那他们就没有交集,也不存在
②A数列有无限多的可能
用第三个样例举例
2 7 12 17 22
7 12 17 22
为什么是无数多个呢,因为A只要包含有7 12 17 22 它向左可以无限延伸,向右也可以无限延伸
所以我们需要一个类似于边界的东西,防止它无限蔓延,反过来说如果没有这个边界,它就是无穷多种可能的,这个边界就是B数列的最后一项也就是说如果A输出想要向右伸展就一定会考虑到C的末项再加一个公差的位置,此时A和B都有这个数,但是C没有,那么不成立,就成功的把A的右边卡死了,同理A的左边就是B的首项要小于A的首项减一个公差
③A数列有有限种可能
那么我们只要考虑在C的一个公差r内我们能放下几个A的公差,左端和右端都可以放并且不影响,所以它们对答案的贡献为
(
d
c
/
d
a
)
2
(d_c/d_a)^2
(dc/da)2
记得要MOD1e9+7
/****************
*@description:for the Escape Project
*@author: Nebula_xuan
* @Date: 2022-05-01 09:43:25
*************************************************************************/
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int MOD = 1e9 + 7;
long long gcd(long long a, long long b)
{
return b ? gcd(b, a % b) : a;
}
int main()
{
int t;
cin >> t;
while (t--)
{
long long b, q, y, c, r, z;
cin >> b >> q >> y >> c >> r >> z;
if (r % q || (c - b) % q || c < b || c + (z - 1) * r > b + (y - 1) * q)
{
puts("0");
continue;
}
if (c + r * z > b + (y - 1) * q || c - r < b)
{
puts("-1");
continue;
}
long long ans = 0;
for (long long i = 1; i * i <= r; i++)
{
if (r % i == 0)
{
if (i * q / gcd(i, q) == r)
{
ans = (ans + r / i * r / i) % MOD;
}
if (i * i != r)
{
int t = r / i;
if (t * q / gcd(t, q) == r)
{
ans = (ans + r / t * r / t) % MOD;
}
}
}
}
cout << ans << endl;
}
}