牛客寒假算法基础集训营
第一场
E炸鸡块的君的高中会议
题目
样例
思路
首先看到这个题目数据范围就可以知道这不是一个可以暴力过的题。所以应该要推一个结论。
我们可以将这个同学的一来一回看成一组,那么就可以理解为一个来回中n可以减少n-(m-1)个人。
那么我们现在要让所有人都进去,那就是看n/(m-1)的数量。
但是有可能存在一些情况,就是说当你的倒数第二组中的回来的那趟使得n变为m,那总数就要-1,还有如果是你算的最后一组中的进去的那一趟是0的话,就代表你不需要人出来,所以也是总数-1.其余情况都是总数+1,因为你还存在着一些人需要再进去,而这些人一定小于m-1更加小于m。
但是!!!这题的重点是不要忘记了当任何数字模1都是0,所以要将m==2的情况单独拿出来判断!
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> PII;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
//
int t;cin >> t;
while(t--)
{
int n, m;cin >> n >> m;
if(m == 1 && n != 1) cout << "-1" << endl;
else if(m == n) cout << "1" << endl;
else if(m == 2)
{
cout << (n-1)*2-1 << endl;
}else
{
int ans = 0;
int cnt = n/(m-1);
if(n%(m-1) == 1)
{
ans = 2*cnt;
ans--;
}else if(n % (m-1) == 0)
{
ans = 2*cnt;
ans--;
}else
{
ans = cnt*2+1;
}
cout << ans << endl;
}
}
return 0;
}
F 中位数切分
题目
样例
思路以及证明
因为整个数列中的数只有两种情况,即大于等于m和小于m两种情况,所以可以直接将原来的数列抽象成01串的形式,我们大于等于m的数为1,小于m的数为0。
又因为我们现在要让1处于中间位置,那么我们很容易得出:假设存在某个区间满足题设,若想要这个区间使用的1数量最少,那么总是存在这样一种情况即1的数量比0的数量多1个。
由此我们可以推出,假设存在K个满足条件的区间,其中K越大越好,那么一定有每个区间的1数量比0数量多一个。由此得出,区间的数量就是1的数量-0的数量,即K = cnt1 -cnt0。
假设1比0要少,显然无法存在这样的区间,那么就输出-1
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> PII;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
//
int t;cin >> t;
while(t--)
{
int n, m;
cin >> n >> m;
int cnt1 = 0, cnt0 = 0;
for(int i = 1;i <= n;++i)
{
int temp;cin >> temp;
if(temp >= m) cnt1++;
else cnt0++;
}
if(cnt1 > cnt0) cout << cnt1-cnt2 << endl;
else cout << "-1" << endl;
}
return 0;
}
后话
比赛的时候想到了1比0多1个这个性质,但是并没有继续往下想这个性质与区间数量的关系,整了一个枚举断点+删去不合法区间的操作...甚至还用上了栈....完全走远了。
下次见到这种题目其实根据过题人数这么多可以大胆猜一个简单结论,然后再进行证明。记录下来长个记性qwq。