在比赛时看见这题也是一脸懵,不知道题目什么意思,我想的是有没有让我们输入一串数据,我怎么知道那个特殊的会在哪呢,想了很久也没有想出来,然后看了题解之后才明白,这题根本就没有标准答案,甚至可以说你自己可以设置你的数据来得到你自己下想要的答案;本质上就是一个二分查找;就是你看左边一半的值是否正常,如果正常那就去搜另外一边的,直到最后只剩下一个元素;那个元素就是你所要求的答案;
#include<stdio.h>
long long t, n;
long long a[200010], f[200010];
int main()
{
scanf("%lld", &t);
while (t--)
{
scanf("%lld", &n);
for (long long i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
f[i] = f[i - 1] + a[i];
}
long long l = 1, r = n, ans = 0;
while (l <= r) {
long long mid = (l + r) / 2;
printf("? %d ", (mid - l + 1));
for (long long i = l; i <= mid; i++) {
printf("%lld ", i);
}
printf("\n");
fflush(stdout);
long long x = 0;
scanf("%lld", &x);
if (x == f[mid] - f[l - 1]) {
l = mid + 1;
}
else {
r = mid - 1;
ans = mid;
}
}
printf("! %lld\n", ans);
fflush(stdout);
}
return 0;
}
https://codeforces.com/contest/1807/problem/G1
思路:
这题刚开始看着比较像一个dp的题,首先进行排序,然后dp过去,但是我动态规划学的不好,没推出来表达式,于是想了想,又感觉这题贪心能写,先排序,然后求其前缀和,然后对每一个元素进行判断,如果大于其前面的前缀和,则一定不可能,就要输出no;当遍历完后,如果没有这种情况出现,则输出yes;这是为什么呢,我们想一种极端条件,1,1,2,4,8......这种情况是每个新的数都是前面所有数的总和,然后我们再看,可以构造出9吗,可以,10,也可以,11,行,一直到16,你会发现都能构造,也就是说只要低于前面的前缀和的数都能得到;
代码:
#include<stdio.h>
#include<algorithm>
#include<algorithm>
using namespace std;
int t, n, m;
int a[50010];
long long sum[50010];
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 0; i < 50001; i++)
{
sum[i] = 0;
}
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
sort(a, a + n);
sum[0] = a[0];
for (int i = 1; i < n; i++)
{
sum[i] = sum[i - 1] + a[i];
}
int flag = 1;
if (n == 1)
{
if (a[0] == 1)
{
printf("yes\n");
}
else
{
printf("no\n");
}
}
else
{
if (a[0] == 1 && a[1] == 1)
{
for (int i = 1; i < n; i++)
{
if (a[i] > sum[i - 1])
{
flag = 0;
break;
}
}
if (flag == 1)
{
printf("yes\n");
}
else
{
printf("no\n");
}
}
else
{
printf("no\n");
}
}
}
return 0;
}
https://codeforces.com/contest/1807/problem/G2
这题和上题的区别就是这题的数据范围更大,这就导致dp的兄弟们有点难受了;但是还好我用的贪心,就把数组开大一点就行了;
代码:
#include<stdio.h>
#include<algorithm>
#include<algorithm>
using namespace std;
int t, n, m;
int a[500010];
long long sum[500010];
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 0; i < 500001; i++)
{
sum[i] = 0;
}
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
sort(a, a + n);
sum[0] = a[0];
for (int i = 1; i < n; i++)
{
sum[i] = sum[i - 1] + a[i];
}
int flag = 1;
if (n == 1)
{
if (a[0] == 1)
{
printf("yes\n");
}
else
{
printf("no\n");
}
}
else
{
if (a[0] == 1 && a[1] == 1)
{
for (int i = 1; i < n; i++)
{
if (a[i] > sum[i - 1])
{
flag = 0;
break;
}
}
if (flag == 1)
{
printf("yes\n");
}
else
{
printf("no\n");
}
}
else
{
printf("no\n");
}
}
}
return 0;
}
这两天为了应付答辩,一直在看Java的视频,看的很快,本来以为学Java会很简单,但是现实很残酷,两天的匆忙应付得到了报应,我不得不进行反思,我真的适合算法组吗,我希望我自己是一个聪明绝顶的人,但是现实很残酷,我并不能将算法和Java两者兼顾,我的精力是有限的,我在接下来的时间里面会认真的去学习Java,我相信自己会积极调整自己的状态,在项目组做出一点成绩;我会给自己每天两个小时写蓝桥杯题目的时间,为接下来的蓝桥杯做准备;