Codeforces Round #725 (Div. 3) A-D,F题解

A. Stone Game

思路:总共3种情况,都从最左端被拿走,都从最右端被拿走,左侧的从最左端被拿走且右侧的从最右端被拿走,取最小值即可

代码:

//CF-725.A
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

typedef long long ll;
typedef pair<int, int>P;
typedef vector<int>vec;

#define INF 0x3f3f3f3f
const double EPS = 1e-18;
const int MOD = 1e9 + 7;
const int maxn = 8e4 + 1;

int T;
int N, A[maxn];

void solve()
{
	int maxi = -1, mini = -1, maxa = -1, mina = INF;
	for (int i = 0; i < N; i++)
	{
		if (A[i] < mina)
		{
			mina = A[i];
			mini = i;
		}
		if (A[i] > maxa)
		{
			maxa = A[i];
			maxi = i;
		}
	}
	if (mini < maxi)
	{
		int ans[3];
		ans[0] = mini + 1 + N - maxi;
		ans[1] = max(mini, maxi) + 1;
		ans[2] = N - min(mini, maxi);
		int res = INF;
		for (int i = 0; i < 3; i++)
			res = min(res, ans[i]);
		cout << res << endl;
		return;
	}
	else
		{
			int ans[3];
			ans[0] = maxi + 1 + N - mini;
			ans[1] = max(mini, maxi) + 1;
			ans[2] = N - min(mini, maxi);
			int res = INF;
			for (int i = 0; i < 3; i++)
				res = min(res, ans[i]);
			cout << res << endl;
			return;
		}

}

int main()
{
	IOS;
	cin >> T;
	while (T--)
	{
		cin >> N;
		for (int i = 0; i < N; i++)
			cin >> A[i];
		solve();
	}

	return 0;
}

B. Friends and Candies

思路:只能是从糖多的人那里把糖分给糖少的,所以只要求出糖数大于平均的人数即可,当糖数不能被人数整除时输出-1。

代码:

//CF-725.B
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

typedef long long ll;
typedef pair<int, int>P;
typedef vector<int>vec;

#define INF 0x3f3f3f3f
const double EPS = 1e-18;
const int MOD = 1e9 + 7;
const int maxn = 2e5 + 1;

int T;
ll N, A[maxn];
void solve()
{
	int sum = 0, ans = 0;
	int avg;
	for (int i = 0; i < N; i++)
		sum += A[i];
	if (sum % N)
	{
		cout << -1 << endl;
		return;
	}
	avg = sum / N;
	for (int i = 0; i < N; i++)
	{
		if (A[i] > avg)
			ans++;
	}
	cout << ans << endl;
}

int main()
{
	IOS;
	cin >> T;
	while (T--)
	{
		cin >> N;
		for (int i = 0; i < N; i++)
			cin >> A[i];
		solve();
	}

	return 0;
}

C. Number of Pairs

又是因为没开longlongWA了半天。。。

思路:分治法,不断将数列分为左右两个数列,完全在其中一个数列中的数对数量可以递归求得。合并的同时将数列排序,对于跨两个数列的数对,只需枚举左边数列中的数,在右边找加上它之后处于区间内的数的个数即可。

代码:

//CF-725.C
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

typedef long long ll;
typedef pair<int, int>P;
typedef vector<int>vec;

#define INF 0x3f3f3f3f
const double EPS = 1e-18;
const int MOD = 1e9 + 7;
const int maxn = 1e9 + 1;

int T;
ll n, l, r;
vec A;

ll merge_solve(vec& a)
{
	ll ans = 0;
	ll d = a.size();
	if (d <= 1)
		return 0;
	vec b(a.begin(), a.begin() + d / 2);
	vec c(a.begin() + d / 2, a.end());
	ans += merge_solve(b);
	ans += merge_solve(c);

	ll ai = 0, bi = 0, ci = 0;
	while (ai < d)
	{
		if (bi < b.size() && (ci == c.size() || b[bi] < c[ci]))
		{
			if (b[bi] <= r)//只有小于右边界才可能可以
			{
				int hi = r - b[bi], lo = l - b[bi] - 1;
				ans += upper_bound(c.begin(), c.end(), hi) - upper_bound(c.begin(), c.end(), lo);
			}
			a[ai++] = b[bi++];
		}
		else
			a[ai++] = c[ci++];
	}

	return ans;
}

void solve()
{
	cout << merge_solve(A) << endl;
}

int main()
{
	IOS;
	cin >> T;
	while (T--)
	{
		A.clear();
		cin >> n >> l >> r;
		for (int i = 0; i < n; i++)
		{
			int num;
			cin >> num;
			A.push_back(num);
		}
		solve();
	}

	return 0;
}

D. Another Problem About Dividing Numbers

思路:当K==1时,如果A和B不相等并且其中一个能整除另外一个时才YES,否则NO。当K!=1时,计算操作次数的上限,当把每个数都除到1的时候操作次数最多,所以直接统计每个数的质因数个数即可,两个数质因数的和M就是允许操作的最大次数。小于这个次数的操作显然都可以完成。如果K<=M,就YES,否则NO。

代码:

//CF-725.D
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

typedef long long ll;
typedef pair<int, int>P;
typedef vector<int>vec;

#define Y "YES"
#define N "NO"
#define INF 0x3f3f3f3f
const double EPS = 1e-18;
const int MOD = 1e9 + 7;
const int maxn = 1e9 + 1;

int T, A, B, K;
vec prime;

bool isprime(int n)
{
	if (n == 0 || n == 1)
		return false;
	for (int i = 2; i <= sqrt(n); i++)
	{
		if (!(n % i))
			return false;
	}

	return true;
}

void solve()
{
	int numa = 0, numb = 0, index = 0;
	if (K == 1)
	{
		if ((A != B) && (A % B == 0 || B % A == 0))
		{
			cout << Y << endl;
			return;
		}
		else
			cout << N << endl;
	}
	else
	{
		while (A != 1 && index < prime.size())
		{
			if (!(A % prime[index]))
			{
				A /= prime[index];
				numa++;
			}
			else
				index++;
		}
		if (A != 1)
			numa++;
		index = 0;
		while (B != 1 && index < prime.size())
		{
			if (!(B % prime[index]))
			{
				B /= prime[index];
				numb++;
			}
			else
				index++;
		}
		if (B != 1)
			numb++;
		int times = numa + numb;
		cout << (times >= K ? Y : N) << endl;
	}
}

int main()
{
	IOS;
	for (int i = 0; i <= 1e5 + 7; i++)
	{
		if (isprime(i))
			prime.push_back(i);
	}
	cin >> T;
	while (T--)
	{
		cin >> A >> B >> K;
		solve();
	}

	return 0;
}

F. Interesting Function

没想到F题居然这么简单,快结束的时候看见一堆人过了才赶紧去做的。。。

思路:每加1就会有1个数字改变,如果进位了,每进1位就额外有1个数字改变,对于从a加到b,可以看作是从1加到b再减去从1加到a,进位的次数直接分别除以10,100……即可。

代码:

//CF-725.F
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

typedef long long ll;
typedef pair<int, int>P;
typedef vector<int>vec;

#define Y "YES"
#define N "NO"
#define INF 0x3f3f3f3f
const double EPS = 1e-18;
const int MOD = 1e9 + 7;
const int maxn = 1e9 + 1;

ll T, L, R;
ll A[10] = { 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000 };

void solve()
{
	ll ansr = 0, ansl = 0;
	for (int i = 0; i < 10; i++)
	{
		ansr += R / A[i];
		ansl += L / A[i];
	}
	cout << ansr - ansl << endl;
}

int main()
{
	IOS;
	cin >> T;
	while (T--)
	{
		cin >> L >> R;
		solve();
	}

	return 0;
}
posted @ 2022-03-02 20:08  Prgl  阅读(46)  评论(0)    收藏  举报