题目链接:Dashboard - Codeforces Round 872 (Div. 2) - Codeforces
A - LuoTianyi and the Palindrome String
解题思路:如果全部相等就不行要不然答案就是n或者n-1了。
#include <bits/stdc++.h>
using namespace std;
const int mx = 2e5 + 10;
using ull = unsigned long long;
using ll = long long;
int main() {
auto check1 = [](string &s) {
for (int i=1;i<s.length();i++) {
if (s[i] != s[i-1])
return false;
}
return true;
};
auto check2 = [](string &s) {
int len = s.length();
for (int i=0; i<len/2;i++) {
if (s[i] != s[len-1-i]) {
return false;
}
}
return true;
};
int t;
scanf("%d", &t);
while (t--) {
string s;
cin>>s;
if (check1(s)) {
puts("-1");
continue;
}
if (!check2(s)) {
printf("%d\n", s.length());
} else {
printf("%d\n", s.length()-1);
}
}
return 0;
}
解题思路:n-1 * m的格子肯定是最大值减去最小值的,然后剩下一行就看是最大值减去次小值还是次大值减去最小值更好了。
#include <bits/stdc++.h>
using namespace std;
const int mx = 2e2 + 10;
using ull = unsigned long long;
using ll = long long;
#define inf 0x3f3f3f3f
int a[mx*mx];
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, m;
scanf("%d%d", &n, &m);
for (int i=1;i<=n*m;i++) {
scanf("%d", a + i);
}
sort(a + 1, a + 1 + n * m);
if (n < m) swap(n, m);
ll ans1 = 1ll * (n - 1) * m * (a[n*m] - a[1]) + (m-1) * (a[n*m] - a[2]);
ll ans2 = 1ll * (n - 1) * m * (a[n*m] - a[1]) + (m-1) * (a[n*m-1] - a[1]);
printf("%lld\n", max(ans1, ans2));
}
return 0;
}
解题思路:贪心枚举哪个固定值先放,然后就沿着这个值的位置两边展开就行了。
#include <bits/stdc++.h>
using namespace std;
const int mx = 1e5 + 10;
using ull = unsigned long long;
using ll = long long;
#define inf 0x3f3f3f3f
int a[mx];
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, m;
scanf("%d%d", &n, &m);
set <int> seat;
int num1 = 0, num2 = 0;
for (int i=1;i<=n;i++) {
scanf("%d", a+i);
if (a[i] == -1)
num1++;
else if (a[i] == -2)
num2++;
else
seat.insert(a[i]);
}
int ans = max(num1, num2) + (int)seat.size();
int i = 1;
for (auto it=seat.begin(); it != seat.end(); it++, i++) {
ans = max(ans, min(*it - i, num1) + min(m - *it - ((int)seat.size() - i), num2) + (int)seat.size());
}
printf("%d\n", min(ans, m));
}
return 0;
}
D2 - LuoTianyi and the Floating Islands (Hard Version)
解题思路:对于k为奇数来说,不管k个点怎样分布,肯定只有一个点满足条件。试想一下你现在找到了一个x点他到所有k的点的距离最小。当你任意移动x一个位置,肯定大于x这个点的所有距离,因为k不是偶数无法使得移动之后一半点增加1一半点减小一。所以当k是奇数的时候答案是1。如果k是偶数的情况下,那么就存在链的情况使得一种k点分布的情况下有多个点满足条件。首先在C(n,k)的分布情况下肯定都至少有一个点满足最小的条件。为了防止我们重复计算,当有链的情况下肯定是不值1个点满足最小值。并且把k分成2分,如果一个边(u,v)满足条件,那么以v为子树的点有k/2个,剩下的k/2就不在v这棵子树上。因此我们可以枚举边的贡献,来防止重复计算,因为一个n个点链他的边就是n-1条。所以不会重复计算C(n,k)中至少一次的贡献。
#include <bits/stdc++.h>
using namespace std;
#define k_m (k / 2 + 1)
const int mx = 2e5 + 10;
const int mod = 1e9 + 7;
using ll = long long;
vector <int> vec[mx];
ll c[mx];
int siz[mx];
int n,k;
ll base;
ll qpow(ll x, ll y)
{
ll ans = 1;
while (y) {
if (y & 1) ans = ans * x % mod;
y >>= 1;
x = x * x % mod;
}
return ans;
}
ll C(int nn, int mm)
{
if (nn < mm)
return 0;
return c[nn] * qpow(c[mm], mod-2) % mod * qpow(c[nn-mm], mod-2) % mod;
}
ll dfs(int u, int f)
{
ll ans = 0;
siz[u] = 1;
for (int v: vec[u]) {
if (v == f)
continue;
ans += dfs(v, u);
siz[u] += siz[v];
ans += (C(siz[v], k/2) * C(n-siz[v], k/2)) % mod;
ans %= mod;
}
return ans;
}
int main()
{
c[0] = 1;
scanf("%d%d", &n, &k);
for (int i=1;i<=n;i++) {
c[i] = c[i-1] * i % mod;
}
base = C(n, k);
ll ans = base;
for (int i=1;i<n;i++) {
int u,v;
scanf("%d%d", &u, &v);
vec[u].push_back(v);
vec[v].push_back(u);
}
if (k & 1) {
puts("1");
return 0;
}
ans += dfs(1, 0);
ans %= mod;
printf("%lld\n", ans * qpow(base, mod-2) % mod);
return 0;
}