CF #764 Div.3
B题 Make AP
给定a b c
使其中一个数 乘 任意正整数m 问是否能构成成差数列
我们可以想到等差数列的性质
2
b
=
a
+
c
2b = a + c
2b=a+c
思路:分类讨论 a b c的三种情况
- 2b = a + c 直接构成等差数列
- 2b < a + c 说明b偏小了 (a + c) % (2 * b) == 0 ? YES : NO
- 2b > a + c 说明a或者c偏小了 ( (2b - a) % c == 0 || (2b - c) % a == 0 ) ? YES : NO
int main()
{
std::ios::sync_with_stdio(false);cin.tie(0);
int t;
cin >> t;
while(t--)
{
int a, b, c;
cin >> a >> b >> c;
if(2 * b == a + c) cout << "YES" << endl;
else if(2 * b < a + c)
{
if((a + c) % (2 * b) == 0) cout << "YES" << endl;
else cout << "NO" << endl;
}
else if(2 * b > a + c)
{
if( (2 * b - a) % c == 0 || (2 * b - c) % a == 0 ) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
return 0;
}
题C Division by Two and Permutation
给n个数 我们可以对任意一个数做除2操作 问是否能构成一个1~n的序列
思路: 用STL的set做很容易理解,每输入一个数,当它大于n时除以2,小于n时判断set中是否有该数,
若没有insert到set中,若有则继续除以2,若该数对于set中的数没有任何贡献,则必不满足条件。
int main()
{
std::ios::sync_with_stdio(false);cin.tie(0);
int t;
cin >> t;
while(t--)
{
set<int> s;
bool flag = true;
int n;
cin >> n;
for(int i = 1; i <= n; i++)
{
int x;
cin >> x;
while(x > n) x /= 2;
while(s.count(x)) x /= 2;//已存在于集合当中
if(x == 0) flag = false;//如果你一路除下来 你都不能成为序列中的一部分 就必然不能构成序列了
else s.insert(x);
}
cout << (flag ? "YES" : "NO") << endl;
}
return 0;
}
题D Palindromes Coloring
给定字符串s,返回可以通过交换任意两个字符而形成的最短回文字符串的最长长度,但是必须将字符串分割成k个回文字符串
思路:因为提到了最短回文字符串 且一共有k个回文字符串 那么我们首先要想的就是尽量让回文字符串的长度平均
我们首先要从回文的定义入手 回文字符串 意味着对称字符的出现
将成对的字符平均分给k个回文字符串
剩下的多出来的字符 和 之前单个的字符 相加 若是大于k
最短字符串长度加一
int main()
{
ios::sync_with_stdio(false);cin.tie(0);
cin >> t;
while(t--)
{
int n, k;
cin >> n >> k
cin >> s;
ms(letter, 0);
for(int i = 0; i < s.size(); i++)
letter[s[i] - 'a'] ++;
int tot1 = 0, tot2 = 0;
for(int i = 0; i < 26; i++)
{
tot1 += letter[i] / 2;
tot2 += letter[i] % 2;
}
int res = tot1 / k * 2;//成对的字母数量 / 子串数量
if(tot1 % k * 2 + tot2 >= k ) res ++;
cout << res << endl;
}
return 0;
}