Codeforces Round #725 (Div. 3)

这篇博客探讨了计算机科学中与数位变化相关的算法问题,包括找到数组中最大值和最小值的最少操作次数,使得所有朋友的糖果数量相等,计算满足特定条件的数对数量,以及如何在有限步数内使两个数相等。文章通过实例解释了每个问题的解决方案,涉及二分查找、因数计算和数位变化分析等概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A. Stone Game

Polycarp is playing a new computer game. This game has n stones in a row. The stone on the position i has integer power ai. The powers of all stones are distinct.

Each turn Polycarp can destroy either stone on the first position or stone on the last position (in other words, either the leftmost or the rightmost stone). When Polycarp destroys the stone it does not exist any more.

Now, Polycarp wants two achievements. He gets them if he destroys the stone with the least power and the stone with the greatest power. Help Polycarp find out what is the minimum number of moves he should make in order to achieve his goal.

For example, if n=5 and a=[1,5,4,3,2], then Polycarp could make the following moves:

Destroy the leftmost stone. After this move a=[5,4,3,2];
Destroy the rightmost stone. After this move a=[5,4,3];
Destroy the leftmost stone. After this move a=[4,3]. Polycarp destroyed the stones with the greatest and least power, so he can end the game.
Please note that in the example above, you can complete the game in two steps. For example:

Destroy the leftmost stone. After this move a=[5,4,3,2];
Destroy the leftmost stone. After this move a=[4,3,2]. Polycarp destroyed the stones with the greatest and least power, so he can end the game.
Input
The first line contains an integer t (1≤t≤100). Then t test cases follow.

The first line of each test case contains one integer n (2≤n≤100) — the number of stones.

The second line contains n distinct integers a1,a2,…,an (1≤ai≤n) — the power of the stones.

Output
For each test case, output the minimum number of moves required to destroy the stones with the greatest and the lowest power.

  • 找到最大值和最小值所在的位置l, r,比较max(l, r), l + n - r + 1, n - min(l, r) + 1的最小值即可

  • 代码:

#include <bits/stdc++.h>
#define rs register
#define il inline
#define ll long long
#define _for(i, a, b) for(rs int i = a; i <= b; i++)
using namespace std;
const ll N = 1e6 + 10;
ll t, n, m, x;
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> t;
	while(t--) {
		cin >> n;
		ll min_pos = 0, max_pos = 0, MIN = 9999999, MAX = 0;
		for(int i = 1; i <= n; i++) {
			cin >> x;
			if(x < MIN) {
				MIN = x;
				min_pos = i;
			}
			if(x > MAX) {
				MAX = x;
				max_pos = i;
			}
		}
		if(MIN == MAX) {
			cout << 2 << endl;
			continue;
		}
		if(min_pos > max_pos) swap(min_pos, max_pos);
		cout << min(max_pos, min(n - min_pos + 1, min_pos + n - max_pos + 1)) << endl;
	}
	return 0;
} 

B. Friends and Candies

Polycarp has n friends, the i-th of his friends has ai candies. Polycarp’s friends do not like when they have different numbers of candies. In other words they want all ai to be the same. To solve this, Polycarp performs the following set of actions exactly once:

Polycarp chooses k (0≤k≤n) arbitrary friends (let’s say he chooses friends with indices i1,i2,…,ik);
Polycarp distributes their ai1+ai2+…+aik candies among all n friends. During distribution for each of ai1+ai2+…+aik candies he chooses new owner. That can be any of n friends. Note, that any candy can be given to the person, who has owned that candy before the distribution process.
Note that the number k is not fixed in advance and can be arbitrary. Your task is to find the minimum value of k.

For example, if n=4 and a=[4,5,2,5], then Polycarp could make the following distribution of the candies:

Polycarp chooses k=2 friends with indices i=[2,4] and distributes a2+a4=10 candies to make a=[4,4,4,4] (two candies go to person 3).
Note that in this example Polycarp cannot choose k=1 friend so that he can redistribute candies so that in the end all ai are equal.

For the data n and a, determine the minimum value k. With this value k, Polycarp should be able to select k friends and redistribute their candies so that everyone will end up with the same number of candies.

Input
The first line contains one integer t (1≤t≤104). Then t test cases follow.

The first line of each test case contains one integer n (1≤n≤2⋅105).

The second line contains n integers a1,a2,…,an (0≤ai≤104).

It is guaranteed that the sum of n over all test cases does not exceed 2⋅105.

Output
For each test case output:

the minimum value of k, such that Polycarp can choose exactly k friends so that he can redistribute the candies in the desired way;
“-1” if no such value k exists.

  • 找到比均值高的数即可
  • 代码:
#include <bits/stdc++.h>
#define rs register
#define il inline
#define ll long long
#define _for(i, a, b) for(rs int i = a; i <= b; i++)
using namespace std;
const ll N = 1e6 + 10;
ll t, n, m, x[N];
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> t;
	while(t--) {
		cin >> n;
		ll sum = 0;
		for(int i = 1; i <= n; i++) cin >> x[i], sum += x[i];
		sort(x + 1, x + n + 1);
		if(x[1] == x[n]) {
			cout << 0 << endl;
			continue;
		}
		if(sum % n != 0) {
			cout << -1 << endl;
			continue;
		}
		sum = sum / n;
		ll cnt = 0;
		for(int i = n; i >= 1; i--) {
			if(sum < x[i]) {
				cnt++;
			}
		}
		cout << cnt << endl;
	}
	return 0;
} 

C. Number of Pairs

You are given an array a of n integers. Find the number of pairs (i,j) (1≤i<j≤n) where the sum of ai+aj is greater than or equal to l and less than or equal to r (that is, l≤ai+aj≤r).

For example, if n=3, a=[5,1,2], l=4 and r=7, then two pairs are suitable:

i=1 and j=2 (4≤5+1≤7);
i=1 and j=3 (4≤5+2≤7).
Input
The first line contains an integer t (1≤t≤104). Then t test cases follow.

The first line of each test case contains three integers n,l,r (1≤n≤2⋅105, 1≤l≤r≤109) — the length of the array and the limits on the sum in the pair.

The second line contains n integers a1,a2,…,an (1≤ai≤109).

It is guaranteed that the sum of n overall test cases does not exceed 2⋅105.

Output
For each test case, output a single integer — the number of index pairs (i,j) (i<j), such that l≤ai+aj≤r.

  • 如果不要求i, j的大小关系,那么对于每一个x[i],都是二分找到[L,R]这个区间,对于区间内的每一个数都是满足条件的,同时特判i == j的情况是不能成立的,并且i < j和i > j这是两对,所以最后答案/2即可
  • 代码:
#include <bits/stdc++.h>
#define rs register
#define il inline
#define ll long long
#define _for(i, a, b) for(rs int i = a; i <= b; i++)
using namespace std;
const ll N = 1e6 + 10;
ll t, n, m, l, r, x[N];
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> t;
	while(t--) {
		cin >> n >> l >> r;
		for(int i = 1; i <= n; i++) cin >> x[i];
		sort(x + 1, x + n + 1);
		ll ans = 0;
		for(int i = 1; i <= n; i++) {
			if(x[i] > r) break;
			int L = lower_bound(x + 1, x + n + 1, l - x[i]) - x;
			int R = upper_bound(x + 1, x + n + 1, r - x[i]) - x - 1;
			if(L <= i && i <= R) ans--;
			ans += (R - L + 1);
		}
		ans /= 2;
		cout << ans << endl;
	}
	return 0;
} 

D. Another Problem About Dividing Numbers

You are given two integers a and b. In one turn, you can do one of the following operations:

Take an integer c (c>1 and a should be divisible by c) and replace a with ac;
Take an integer c (c>1 and b should be divisible by c) and replace b with bc.
Your goal is to make a equal to b using exactly k turns.

For example, the numbers a=36 and b=48 can be made equal in 4 moves:

c=6, divide b by c ⇒ a=36, b=8;
c=2, divide a by c ⇒ a=18, b=8;
c=9, divide a by c ⇒ a=2, b=8;
c=4, divide b by c ⇒ a=2, b=2.
For the given numbers a and b, determine whether it is possible to make them equal using exactly k turns.

Input
The first line contains one integer t (1≤t≤104). Then t test cases follow.

Each test case is contains three integers a, b and k (1≤a,b,k≤109).

Output
For each test case output:

“Yes”, if it is possible to make the numbers a and b equal in exactly k turns;
“No” otherwise.
The strings “Yes” and “No” can be output in any case.

  • 1.特判1的情况,如果二者相同,肯定不行,如果二者不同,则判断二者是否存在因数关系2.求出a,b的因数个数,二者相加如果大于等于k,则可以在k步内解决
  • 代码:
#include <bits/stdc++.h>
#define rs register
#define il inline
#define ll long long
#define _for(i, a, b) for(rs int i = a; i <= b; i++)
using namespace std;
const ll N = 1e9, N2 = 1e5;
ll t, n, m, k,a,b, cnt;
ll prime[N2];
unordered_map<ll, ll> isprime;
void GetPrime(int n) {//筛选到n
    for(ll i = 1; i <= n; i++) isprime[i] = 1; 
    isprime[1] = 0;
      for(int i = 2; i <= n; i++) {
        if(isprime[i]) prime[++cnt] = i;
          for(int j = 1; j <= cnt && i * prime[j] <= n; j++) {
            isprime[i * prime[j]] = 0;
            if(i % prime[j] == 0) break;
        }
    }
    return ;
}
ll calc(ll x) {
	ll res=0;
	for(int i=1;1ll*prime[i]*prime[i]<=x;i++)
		while(x%prime[i]==0) 
			res++,x/=prime[i];
	if(x>1) res++;
	return res;
}
int main() {
	GetPrime(N2);
	cin >> t;
	while(t--) {
		cin >> a >> b >> k;
		if(k == 1) {
			if(max(a, b) % min(a, b) != 0 || max(a, b) % min(a, b) == 0 && a == b)
				cout << "NO" << endl;
			else
				cout << "YES" << endl;
			continue;
		}
		ll ans = calc(a) + calc(b);
		if(ans >= k) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	return 0;
} 

F. Interesting Function

You are given two integers l and r, where l<r. We will add 1 to l until the result is equal to r. Thus, there will be exactly r−l additions performed. For each such addition, let’s look at the number of digits that will be changed after it.

For example:

if l=909, then adding one will result in 910 and 2 digits will be changed;
if you add one to l=9, the result will be 10 and 2 digits will also be changed;
if you add one to l=489999, the result will be 490000 and 5 digits will be changed.
Changed digits always form a suffix of the result written in the decimal system.

Output the total number of changed digits, if you want to get r from l, adding 1 each time.

Input
The first line contains an integer t (1≤t≤104). Then t test cases follow.

Each test case is characterized by two integers l and r (1≤l<r≤109).

Output
For each test case, calculate the total number of changed digits if you want to get r from l, adding one each time.

  • 有一个规律很易得,就是单独判断每个数位的变化次数。比如对于12,它的变化次数就是12/1 + 12/10 = 13
  • 代码:
#include <bits/stdc++.h>
#define rs register
#define il inline
#define ll long long
#define _for(i, a, b) for(rs int i = a; i <= b; i++)
using namespace std;
const ll N = 1e9, N2 = 1e5;
ll t, n, m, k,a,b, cnt;
inline ll ok(ll x) {
	ll ans = 0;
	for(register ll i = 1; i <= x; i *= 10)
		ans += x / i;
	return ans;
}
int main() {
	cin >> t;
	while(t--) {
		cin >> a >> b;
		cout << ok(b) -ok(a) << endl;
	}
	return 0;
} 

1400了哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顶白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值