A. Boring Apartments
签到题
AC代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char s[5];
void solve() {
scanf("%s", &s);
int len = strlen(s);
printf("%d\n", (s[0] - '0' - 1) * 10 + (len + 1) * len / 2);
}
int main() {
int t;
scanf("%d", &t);
for (int i = 0; i < t; ++i) {
solve();
}
return 0;
}
B. Yet Another Bookshelf
思路
签到题,取出前导零和后导零,记录中间有多少个零,可以先将两边的1移动到一起,然后一起往中间移动,也就是记录中间中间有多少个零。
AC代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 100 + 5;
int a[maxn];
void solve() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
int l, r;
for (l = 0; l < n; ++l) {
if (a[l]) {
break;
}
}
for (r = n - 1; r >= 0; --r) {
if (a[r]) {
break;
}
}
int ans = 0;
for (int i = l; i <= r; ++i) {
if (a[i] == 0) {
ans++;
}
}
printf("%d\n", ans);
//puts("--------");
}
int main() {
int t;
scanf("%d", &t);
for (int i = 0; i < t; ++i) {
solve();
}
return 0;
}
C - Dominant Piranha: 简单贪心
思路:
签到题,直接记录最大值的边界位置即可,例如5 5 4 3 5, 2和5都是边界位置,这些边界位置都是优势食人鱼。
AC代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 5;
int a[maxn];
void solve() {
int n;
scanf("%d", &n);
int mx = 0;
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
mx = max(mx, a[i]);
}
a[0] = a[n + 1] = mx;
int ans = -1;
for (int i = 1; i <= n; ++i) {
if (a[i] == mx && (a[i - 1] != mx || a[i + 1] != mx)) {
ans = i;
break;
}
}
printf("%d\n", ans);
//puts("--------");
}
int main() {
int t;
scanf("%d", &t);
for (int i = 0; i < t; ++i) {
solve();
}
return 0;
}
D. Districts Connection: 暴力
思路:
直接暴力找两个不同的值连接起来即可。
AC代码
#include<stdio.h>
#include<string.h>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 5;
int a[maxn], vis[maxn];
void solve() {
int n;
set<int> st;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
st.insert(a[i]);
}
if (st.size() == 1) {
puts("NO");
return;
}
puts("YES");
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; ++i) {
if (vis[i]) continue;
for (int j = 1; j <= n; ++j) {
if (i == j) continue;
if (a[i] != a[j]) {
printf("%d %d\n", i, j);
vis[j] = true;
break;
}
}
}
}
int main() {
int t;
scanf("%d", &t);
for (int i = 0; i < t; ++i) {
solve();
}
return 0;
}
E. Two Round Dances 组合数+圆排列
思路:
循环排列,如果以r为周长,则不同的方案数为,A(r, n) / r = r, 如果r == n,则方案数为(n - 1)!;
左集合:先从n中选n/2个,再进行圆排列,一共有C(n / 2, n) * A(n / 2, n / 2) / (n / 2) == > C(n / 2, n) * (n / 2 - 1)!;
右集合:由于前面已经选了n/2个,所以右集合的元素固定,然后进行圆排列 A(n / 2, n / 2) / (n / 2) == > (n / 2 - 1)!;
将左集合的方案数*右集合的方案数乘起来就是总方案数了,但我们仔细想一想真的是这样吗,其实不然,但我们选取一半的集合作为
左集合的时候,右集合唯一, 但是会重复算一次,举个简单的例子,n = 4时,我们不考虑圆排列的情况下,[1, 3], [2, 4]和[2, 4],[1, 3]
是不是一样的,所以我们最后需要除以2.
AC代码
#include<stdio.h>
#include<string.h>
#include<map>
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
//求组合数C(m, n);
ll cal(int m, int n) {
if (m == 0 || m == n) {
return 1;
}
if (n < m) {
return 0;
}
return cal(m - 1, n - 1) + cal(m, n - 1);
}
void solve() {
int n;
scanf("%d", &n);
ll C = cal(n / 2, n);
ll A = 1;
for (ll i = 1; i < n / 2; ++i) {
A *= i;
}
printf("%lld\n", C * A * A / 2);
//puts("--------");
}
int main() {
int t = 1;
// scanf("%d", &t);
for (int i = 0; i < t; ++i) {
solve();
}
return 0;
}