A
目测一道难题,十有八九我也不会。
B
思路:枚举圆。
PS:写几何的时候注意精度。
C
思路:首先枚举种类,然后用隔板法求组合数。
#include
using namespace std;
typedef long long LL;
LL C[30][30];
int main()
{
for(int i = 0; i <= 25; i++) {
C[i][0] = 1;
}
for(int i = 1; i <= 25; i++) {
for(int j = 1; j <= i; j++) {
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
int n, k; scanf("%d%d", &n, &k);
LL ans = 0;
for(int i = 1; i <= min(n, k); i++) {
ans += C[n][i] * C[k - 1][i - 1];
}
printf("%lld\n", ans);
return 0;
}
D
思路:贪心。优先选择价值大的,使用的时间尽量靠后。
#include
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
pii a[MAXN];
bool cmp(pii x, pii y) {
return x.second != y.second ? x.second > y.second : x.first < y.first;
}
vector<int> G;
int main()
{
int n; scanf("%d", &n);
int MT = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i].first);
MT = max(MT, a[i].first);
}
G.clear();
for(int i = 1; i <= MT; i++) G.push_back(i);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i].second);
}
sort(a + 1, a + n + 1, cmp);
int ans = 0;
for(int i = 1; i <= n; i++) {
if(G.size() == 0) continue;
if(*G.begin() > a[i].first) continue;
ans += a[i].second;
vector<int> :: iterator it;
it = G.end(); --it;
if(*it <= a[i].first) {
G.erase(it);
}
else {
it = upper_bound(G.begin(), G.end(), a[i].first);
G.erase(--it);
}
}
printf("%d\n", ans);
return 0;
}
E
思路: KMP 即可。 fail[i] 表示第 i 位前面的最长匹配前缀和后缀。
#include
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
char str[MAXN];
int fail[MAXN];
void getfail(char *P) {
fail[0] = 0; fail[1] = 0;
for(int i = 1; P[i]; i++) {
int j = fail[i];
while(j && P[i] != P[j]) {
j = fail[j];
}
fail[i + 1] = P[i] == P[j] ? j + 1 : 0;
}
}
bool judge(int l1, int r1, int l2, int r2) {
int j = 0;
for(int i = l1; i <= r1; i++) {
while(j && str[i] != str[l2 + j]) {
j = fail[j];
}
if(str[i] == str[l2 + j]) {
j++;
}
if(j == r2 - l2 + 1) return true;
}
return false;
}
int main()
{
int t; scanf("%d", &t);
while(t--) {
scanf("%s", str);
getfail(str);
int len = strlen(str);
int j = fail[len];
int ans = 0;
while(j) {
if(3 * j <= len && judge(j, len - j - 1, 0, j - 1)) {
ans = j; break;
}
else {
j = fail[j];
}
}
printf("%d\n", ans);
}
return 0;
}
F
思路: dp1[i] 表示以 a[i] 结尾的最大区间和, dp2[i] 表示以 a[i] 开头的最大区间和。
答案就是 max1<=i+2<=n(dp1[i]+(maxi+2<=j<=ndp2[j]))
#include
using namespace std;
typedef long long LL;
const int MAXN = 5e5 + 10;
const int INF = -1e8;
int a[MAXN];
int dp1[MAXN], dp2[MAXN];
int Max[MAXN];
int main()
{
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for(int i = 0; i <= n + 1; i++) {
dp1[i] = dp2[i] = Max[i] = INF;
}
for(int i = 1; i <= n; i++) {
dp1[i] = max(dp1[i - 1] + a[i], a[i]);
}
for(int i = n; i >= 1; i--) {
dp2[i] = max(dp2[i + 1] + a[i], a[i]);
Max[i] = max(Max[i + 1], dp2[i]);
}
int ans = INF;
for(int i = 1; i <= n - 2; i++) {
ans = max(dp1[i] + Max[i + 2], ans);
}
printf("%d\n", ans);
return 0;
}
G
解法一:先二分最小的最大值 Max ,然后选择所有的不大于 Max−1 的元素,之后不够的话补上 Max 即可。
解法二:直接用堆去维护,最多入队 2∗N 个元素。
#include
#include
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 10;
int a[MAXN], b[MAXN];
int n;
LL Work(int o) {
LL ans = 0;
for(int i = 1; i <= n; i++) {
if(b[1] + a[i] > o) {
break;
}
int pos = upper_bound(b + 1, b + n + 1, o - a[i]) - b - 1;
ans += pos;
}
return ans;
}
int ans[MAXN], top;
void Put(int o) {
top = 0;
for(int i = 1; i <= n; i++) {
if(b[1] + a[i] > o) {
break;
}
int pos = upper_bound(b + 1, b + n + 1, o - a[i]) - b - 1;
for(int j = 1; j <= pos; j++) {
ans[top++] = a[i] + b[j];
}
}
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for(int i = 1; i <= n; i++) {
scanf("%d", &b[i]);
}
sort(a + 1, a + n + 1);
sort(b + 1, b + n + 1);
int l = a[1] + b[1], r = a[n] + b[n];
int Max;
while(r >= l) {
int mid = l + r >> 1;
LL num = Work(mid);
if(num >= 1LL * n) {
Max = mid;
r = mid - 1;
}
else {
l = mid + 1;
}
}
Put(Max - 1);
int left = n - top;
for(int i = 0; i < left; i++) {
ans[top++] = Max;
}
sort(ans, ans + top);
for(int i = 0; i < top; i++) {
printf("%d\n", ans[i]);
}
return 0;
}
H
思路: ∑ni=1a[i]>2∗max1<=i<=na[i]
#include
using namespace std;
typedef long long LL;
const int MAXN = 1e6 + 10;
int a[MAXN];
int main()
{
int n; scanf("%d", &n);
int ans = -1;
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
int sum = 0;
int Max = 0;
for(int i = 0; i < n; i++) {
sum += a[i];
Max = max(Max, a[i]);
if(sum > 2 * Max) {
ans = i + 1;
break;
}
}
printf("%d\n", ans);
return 0;
}
I
水题不说了。
J
很神奇,答案就是把 N 反过来输出。
K
目测语文阅读理解题目。读懂可以AC
L
最多三个人,很多人看错题意了。随便写都可以过
M
模拟即可。
#include
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e3 + 10;
char str[MAXN];
int num[30];
int main()
{
int n; scanf("%d", &n);
scanf("%s", str);
for(int i = 0; i < 26; i++) num[i] = 0;
for(int i = 0; str[i]; i++) {
num[str[i] - 'a']++;
}
int ans = 0;
for(int i = 0; i < 26; i++) {
while(num[i]) {
num[i]--;
for(int j = i + 1; j < 26; j++) {
if(num[j]) {
num[j]--;
}
else {
break;
}
}
ans++;
}
}
printf("%d\n", ans);
return 0;
}