A. Elections
题意就是给你三个数,然后让你求出要超过其他两个数,他需要再加多少。
就是判断出所有情况即可。
如果三个数都相同的时候 就都只需要加1。
如果两个数相同并且大于另外一个数,则这两个数需要加1,而另外一个数则需要加他们的差值再加1。
三个数都不同就是和最大值有关了。除了最大的那个数本身不需要再加1,其他两个数都需要加差值再加1.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int inf = 0x3f3f3f3f;
const int MAXN = 1e5 + 10;
int n, m, T;
int flag;
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> T;
while (T--) {
ll a, b, c;
cin >> a >> b >> c;
if (a == b && b == c) {
cout << 1 << " " << 1 << " " << 1 << endl;
continue;
}
ll maxn = max(a, max(b, c));
if (a == b && a == maxn) {
cout << 1 << " " << 1 << " " << maxn - c+1<< endl;
continue;
} else if (a == c && a == maxn) {
cout << 1 << " " << maxn - b+1 << " " << 1 << endl;
continue;
} else if (b == c && b == maxn) {
cout << maxn - a +1<< " " << 1 << " " << 1 << endl;
continue;
}
cout << (maxn - a ? maxn - a + 1 : 0) << " " << (maxn - b ? maxn - b + 1 : 0) << " "
<< (maxn - c ? maxn - c + 1 : 0) << endl;
}
return 0;
}
B. Make it Divisible by 25
题意是给你一个数,看你最少删去几个数可以让他变成25的倍数,题目保证有解且没有前导零。
因为要是25的倍数,所以我们可以观察下25倍数的特征,即后面两个数字只有25,50,75,00。这四种情况。所以我们就是遍历这四种情况即可。
我是字符串读入,然后翻转一下。就把找四种情况变成了找两种情况。
即如果当前位是0 就往后找5和0.
如果当前位数是5就往后找2和7.
然后如果找到了就求出需要减去几位,记录最小值即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int inf = 0x3f3f3f3f;
const int MAXN = 1e5 + 10;
int n, m, T;
int flag;
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> T;
while (T--) {
// ll a;
// cin>>a;
string s;
cin >> s;
reverse(s.begin(),s.end());
// cout<<s<<endl;
int len = s.size();
int ans=100;
for (int i = 0; i < len; i++) {
if(s[i]=='0'){
for(int j=i+1;j<len;j++){
if(s[j]=='0'||s[j]=='5'){
ans=min(j-1,ans);
break;
}
}
}else if(s[i]=='5'){
for(int j=i+1;j<len;j++){
if(s[j]=='2'||s[j]=='7'){
ans=min(j-1,ans);
break;
}
}
}
}
cout<<ans<<endl;
}
return 0;
}
C. Save More Mice
简单贪心。很显然,让先靠近洞的老鼠先走是最好的,因为如果你让后面的老鼠先走,那么他走到洞口需要的步数会比前面的老鼠多。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int inf=0x3f3f3f3f;
const int MAXN=4e5+10;
int n,m,T;
int flag;
int a[MAXN];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>T;
while(T--){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i];
}
sort(a+1,a+1+m);
int num=0;
ll b=0;
for(int i=m;i>0;i--){
if(b<a[i]){
num++;
b+=n-a[i];
}else{
break;
}
}
cout<<num<<endl;
}
return 0;
}
D1. All are Same
因为是简化版本,所以暴力也能过。
因为是减去一个数k次,使得所有的数相同,显然就是一个同余的问题。
因为最小值减去这个数就相当于每个数都再减一遍这个数,没有什么意义,所以可以吧最小值当基准,每个数减去最小值得到的数,就是他们需要通过减去某个数而减到0的数。
即转化成了差值的最大公因数。(我的代码是直接暴力每个数都求一下,因为看着暴力就过了,就没多想了)。
然后所有数都相同的情况特判一下就行了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int inf=0x3f3f3f3f;
const int MAXN=1e5+10;
int n,m,T;
int flag;
int a[MAXN];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
if(a[1]==a[n]){
cout<<-1<<endl;
continue;
}
int v;
int ans=0;
for(int i=1;i<=a[n]-a[1];i++){
flag=1;
for(int j=1;j<=n;j++){
if((a[j]-a[1])%i){
flag=0;
break;
}
}
if(flag){
ans=max(ans,i);
}
}
cout<<ans<<endl;
}
return 0;
}
D2. Half of Same
D2和D1的区别就是 ,D2只需要一半的数相同就行了。
所以我们就是以某个数为基准,即以他为最小值,然后遍历后面数的差值。
找到这个差值的因子,check一下。
即检查下后面是否有一半即以上的数可以相同。更新最大值即可。
然后记得特判即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int inf = 0x3f3f3f3f;
const int MAXN = 1e5 + 10;
int n, m, T;
int flag;
ll a[105];
bool check(int x, int d)
{
int cnt = 0;
for (int i = x; i <= n; i++) {
if ((a[i] - a[x]) % d == 0) {
cnt++;
}
}
return cnt >= n / 2;
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + 1 + n);
flag = 0;
for (int i = 1; i <= n; i++) { //特判
if(flag){
break;
}
for (int j = i+1; j <= n; j++) {
if (a[i] == a[j]&&j-i+1>=n/2) {
cout << -1 << endl;
flag = 1;
break;
}
}
}
if (flag)
continue;
int ans = 0;
for (int i = 1; i <= n / 2 + 1; i++) {
for (int j = i + 1; j <= n; j++) {
int d = a[j] - a[i];
for (int k = 1; k * k <= d; k++) {
if (d % k != 0)
continue;
if (check(i, d / k))//先判断d/k 因为d/k大于等于k 如果d/k可以就不需要判断k了
ans = max(ans, d / k);
else if (check(i, k))
ans = max(ans, k);
}
}
}
cout << ans << endl;
}
return 0;
}
E. Gardener and Tree
就是相当于是求每个点的深度的问题。
那么怎么求每个点的深度呢。
我们一开始遍历整个图。
当某个点他只连了一条边或者,一条边都没有连的时候,就是深度为1的点。
而当我将这些点移除,再遍历一遍这个图。同样的,连了一条或者没连的是深度为2的点。
但是我们一遍一遍的遍历整个图,肯定会超时。
所以我们换个方式,直接将每个点连的边的条数记录下来。然后如果某个点的边被移除后,导致他的边数小于等于1那么他的深度就是这个点的深度加1。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int inf = 0x3f3f3f3f;
const int MAXN = 4e5 + 10;
int n, m, T;
int k;
int flag;
vector<int> sd(MAXN),bnum(MAXN);
vector<int> v[MAXN];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> T;
while (T--) {
cin >> n >> k;
for(int i=0;i<n;i++){
v[i].clear();
}
for (int i = 1; i <n; i++) {
int x, y;
cin >> x >> y;
x--;
y--;
v[x].push_back(y); //存放无向图
v[y].push_back(x);
}
queue<int> q;
for (int i = 0; i < n; i++) {
sd[i] = inf; //看他是第几次 修剪会被减去
bnum[i] = v[i].size(); //看他连了几条边
if (bnum[i] <= 1) { //如果他只连了一条边 那么说明这个点是叶节点
//之所以要判断小于等于0 是因为 只有一个节点的时候, 第一次裁剪完就没有叶结点了
sd[i] = 1;
q.push(i);
}
}
while (!q.empty()) {
int x = q.front();
q.pop();
for (auto y : v[x]) {
if (bnum[y]-- == 2) {
sd[y] = sd[x] + 1;
q.push(y);
}
}
}
int ans = 0;
for (int i = 0; i < n; i++) {
if (sd[i] >k) {
ans++;
}
}
cout << ans << endl;
}
return 0;
}