Codeforces Round #702 (Div. 3) C - G

传送门.

Sum of Cubes

题目

You are given a positive integer x. Check whether the number x is representable as the sum of the cubes of two positive integers.

Formally, you need to check if there are two integers a and b (1≤a,b) such that a3+b3=x.

For example, if x=35, then the numbers a=2 and b=3 are suitable (23+33=8+27=35). If x=4, then no pair of numbers a and b is suitable.

输入

The first line contains one integer t (1≤t≤100) — the number of test cases. Then t test cases follow.

Each test case contains one integer x (1≤x≤1012).

Please note, that the input for some test cases won’t fit into 32-bit integer type, so you should use at least 64-bit integer type in your programming language.

输出

For each test case, output on a separate line:

1.“YES” if x is representable as the sum of the cubes of two positive integers.
2.“NO” otherwise.

You can output “YES” and “NO” in any case (for example, the strings yEs, yes, Yes and YES will be recognized as positive).

样例

input
7
1
2
4
34
35
16
703657519796
output
NO
YES
NO
NO
YES
YES
YES

题目大意

给你一个数,看是否是俩个立方数的和。

思路

用map打表,打出1-1e4所有数的立方数,然后判定就可

代码

#include <iostream>
#include <map>

using namespace std;

typedef long long ll;

map <ll,ll> mp;

int main()
{
	int t;
	cin >> t;
	
	for(ll i = 1;i <= 10000;i ++) mp[i * i * i] = 1;
	
	while(t --)
	{
		ll x;
		cin >> x;
		
		if(x == 1) 
		{
			cout << "NO" << endl;
			continue;
		}
		int flag = 0;
		
		for(ll i = 1;i <= 10000;i ++)
		{
			if(mp[x - i * i * i] == 1)
			{
				flag = 1;
				break;
			}
		}
		
		if(flag) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	
	return 0;
}

蛮简单的一个题,当时被另一个相似的题困扰住了思路(

Permutation Transformation

题目
A permutation — is a sequence of length n integers from 1 to n, in which all the numbers occur exactly once. For example, [1], [3,5,2,1,4], [1,3,2] — permutations, and [2,3,2], [4,3,1], [0] — no.

Polycarp was recently gifted a permutation a[1…n] of length n. Polycarp likes trees more than permutations, so he wants to transform permutation a into a rooted binary tree. He transforms an array of different integers into a tree as follows:

1.the maximum element of the array becomes the root of the tree;
2.all elements to the left of the maximum — form a left subtree (which is built according to the same rules but applied to the left part of the array), but if there are no elements to the left of the maximum, then the root has no left child;
3.all elements to the right of the maximum — form a right subtree (which is built according to the same rules but applied to the right side of the array), but if there are no elements to the right of the maximum, then the root has no right child.

For example, if he builds a tree by permutation a=[3,5,2,1,4], then the root will be the element a2=5, and the left subtree will be the tree that will be built for the subarray a[1…1]=[3], and the right one — for the subarray a[3…5]=[2,1,4]. As a result, the following tree will be built:

The tree corresponding to the permutation a=[3,5,2,1,4].

Another example: let the permutation be a=[1,3,2,7,5,6,4]. In this case, the tree looks like this:

在这里插入图片描述
The tree corresponding to the permutation a=[1,3,2,7,5,6,4].

Let us denote by dv the depth of the vertex av, that is, the number of edges on the path from the root to the vertex numbered av. Note that the root depth is zero. Given the permutation a, for each vertex, find the value of dv.

输入

The first line contains one integer t (1≤t≤100) — the number of test cases. Then t test cases follow.

The first line of each test case contains an integer n (1≤n≤100) — the length of the permutation.

This is followed by n numbers a1,a2,…,an — permutation a.

输出

For each test case, output n values — d1,d2,…,dn.

样例

input
3
5
3 5 2 1 4
1
1
4
4 3 1 2
output
1 0 2 3 1
0
0 1 3 2

题目大意

给一个数列,最大的数作为树根,最大的数左边的为左枝,右边的为右枝,左边和右边也一样的处理方法。

思路

递归处理,分治,跟快排和归并的思想差不多

代码

#include <iostream>

using namespace std;

typedef long long ll;

const int N = 110;

int t,n;
int a[N],depth[N];

void rec(int l,int r,int d)
{
	if(l > r) return ;
	
	int max = 0,id = 0;
	for(int i = l;i <= r;i ++)
	{
		if(a[i] > max)
		{
			max = a[i];
			id = i;
		}
	}
	
	depth[id] = d;
	
	rec(l,id - 1,d + 1);
	rec(id + 1,r,d + 1);
}

int main()
{
	cin >> t;
	
	while(t --)
	{
		cin >> n;
		
		for(int i = 0;i < n;i ++) cin >> a[i];
		
		rec(0,n - 1,0);
		
		for(int i = 0;i < n;i ++) cout << depth[i] << " ";
		
		puts("");
	}
	
	return 0;
}

没啥难点,就是递归时更新深度即可,还有在递归中记得加递归停止的判断条件

Accidental Victory

题目

A championship is held in Berland, in which n players participate. The player with the number i has ai (ai≥1) tokens.

The championship consists of n−1 games, which are played according to the following rules:

1.in each game, two random players with non-zero tokens are selected;
2.the player with more tokens is considered the winner of the game (in case of a tie, the winner is chosen randomly);
3.the winning player takes all of the loser’s tokens;

The last player with non-zero tokens is the winner of the championship.

All random decisions that are made during the championship are made equally probable and independently.

For example, if n=4, a=[1,2,4,3], then one of the options for the game (there could be other options) is:

1.during the first game, the first and fourth players were selected. The fourth player has more tokens, so he takes the first player’s tokens. Now a=[0,2,4,4];
2.during the second game, the fourth and third players were selected. They have the same number of tokens, but in a random way, the third player is the winner. Now a=[0,2,8,0];
3.during the third game, the second and third players were selected. The third player has more tokens, so he takes the second player’s tokens. Now a=[0,0,10,0];
4.the third player is declared the winner of the championship.

Championship winners will receive personalized prizes. Therefore, the judges want to know in advance which players have a chance of winning, i.e have a non-zero probability of winning the championship. You have been asked to find all such players.

输入

The first line contains one integer t (1≤t≤104) — the number of test cases. Then t test cases follow.

The first line of each test case consists of one positive integer n (1≤n≤2⋅105) — the number of players in the championship.

The second line of each test case contains n positive integers a1,a2,…,an (1≤ai≤109) — the number of tokens the players have.

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

输出

For each test case, print the number of players who have a nonzero probability of winning the championship. On the next line print the numbers of these players in increasing order. Players are numbered starting from one in the order in which they appear in the input.

样例

input
2
4
1 2 4 3
5
1 1 1 1 1
output
3
2 3 4
5
1 2 3 4 5

题目大意

有n个人,每个人有自己的价值ai,现有n - 1次比赛,比赛规则是:如果双方价值不相等,价值高的那方赢;如果价值相等的话,随机让一个人赢。每次比赛赢的那方会夺走输的那方的所有价值,输的那方将不能再参加比赛比赛,当最后只剩下一个人价值不为0的时候,比赛结束。

询问这n个人里有哪些人有机会可以赢得比赛,并输出这些人的编号, 编号需要排序。

思路

先根据下边记录每个人的价值,然后对价值进行排序,然后前缀和,当前缀和小于下一个人的价值时,记录一下(但是不能停止遍历,后边若还有此种情况要更新),说明前边的人都没有获胜的机会,只有后边的人才有获胜的机会

代码

#include <iostream>
#include <map>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

int t;
ll a[N],b[N];

int main()
{
	scanf("%d",&t);
	
	while(t --)
	{
		int n;
		scanf("%d",&n);
		
		for(int i = 1;i <= n;i ++)
		{
			scanf("%lld",&a[i]); 
			b[i] = a[i];
		}
		
		sort(a + 1,a + 1 + n);
		
		ll sum = a[1],ans = 0,id = -1;
		for(int i = 2;i <= n;i ++)
		{
			if(a[i] == a[i - 1]) sum += a[i];
			else
			{
				if(sum < a[i])
				{
					ans = n - i + 1;
					id = a[i - 1];
				}
				sum += a[i];
			}
		}
		
		if(!ans) ans = n;
		printf("%lld\n",ans);
		//cout << id << endl;
		
		for(int i = 1;i <= n;i ++)
		{
			if(b[i] > id) printf("%lld ",i);
		}
		
		for(int i = 1;i <= n;i ++) a[i] = 0,b[i] = 0;
		puts("");
	}
	
	return 0;
} 

刚开始用下标做的wa2,后来改成值了(我太菜了

Equalize the Array

题目

Polycarp was gifted an array a of length n. Polycarp considers an array beautiful if there exists a number C, such that each number in the array occurs either zero or C times. Polycarp wants to remove some elements from the array a to make it beautiful.

For example, if n=6 and a=[1,3,2,1,4,2], then the following options are possible to make the array a array beautiful:

1.Polycarp removes elements at positions 2 and 5, array a becomes equal to [1,2,1,2];
2.Polycarp removes elements at positions 1 and 6, array a becomes equal to [3,2,1,4];
3.Polycarp removes elements at positions 1,2 and 6, array a becomes equal to [2,1,4];

Help Polycarp determine the minimum number of elements to remove from the array a to make it beautiful.

输入

The first line contains one integer t (1≤t≤104) — the number of test cases. Then t test cases follow.

The first line of each test case consists of one integer n (1≤n≤2⋅105) — the length of the array a.

The second line of each test case contains n integers a1,a2,…,an (1≤ai≤109) — array a.

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

输出

For each test case, output one integer — the minimum number of elements that Polycarp has to remove from the array a to make it beautiful.

样例

input
3
6
1 3 2 1 4 2
4
100 100 4 100
8
1 2 3 3 3 2 6 6
output
2
1
2

题目大意

现有一个n个数的序列,问最少删除多少个数字之后,剩下的序列中的所有数都出现C次,原序列中的某些数可以全部删除。

思路

把每个数出现的次数排序,然后遍历即可,找所有出现次数的最大值,然后让n-最大值就是答案

#include <iostream>
#include <map>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

int T;
map<ll,int> mp;

int main()
{
	scanf("%d",&T);
	
	while(T --)
	{
		mp.clear();
		int n;
		ll a[N] = {0};
		scanf("%d",&n);
		
		
		for(int i = 0;i < n;i ++)
		{
			ll x;
			scanf("%lld",&x);
			mp[x] ++;
		} 
		
		map<ll,int> ::iterator it;
		
		int k = 0;
		for(it = mp.begin();it != mp.end();it ++)
		{
			a[k ++] = it -> second;
		}
		
		sort(a,a + k);
		
		//for(int i = 0;i < k;i ++) cout << a[i];
		
		ll ans = 0;
		for(int i = 0;i < k;i ++)
		{
			ans = max(ans,a[i] * (k - i));
		}
		
		printf("%lld",n - ans);
		puts("");
	}
	
	return 0;
} 

很好理解,就是存那个出现次数纠结了许久

Old Floppy Drive

题目

Polycarp was dismantling his attic and found an old floppy drive on it. A round disc was inserted into the drive with n integers written on it.

Polycarp wrote the numbers from the disk into the a array. It turned out that the drive works according to the following algorithm:

1.the drive takes one positive number x as input and puts a pointer to the first element of the a array;
2.after that, the drive starts rotating the disk, every second moving the pointer to the next element, counting the sum of all the elements that have been under the pointer. Since the disk is round, in the a array, the last element is again followed by the first one;
3.as soon as the sum is at least x, the drive will shut down.

Polycarp wants to learn more about the operation of the drive, but he has absolutely no free time. So he asked you m questions. To answer the i-th of them, you need to find how many seconds the drive will work if you give it xi as input. Please note that in some cases the drive can work infinitely.

For example, if n=3,m=3, a=[1,−3,4] and x=[1,5,2], then the answers to the questions are as follows:

1.the answer to the first query is 0 because the drive initially points to the first item and the initial sum is 1.
2.the answer to the second query is 6, the drive will spin the disk completely twice and the amount becomes 1+(−3)+4+1+(−3)+4+1=5.
3.the answer to the third query is 2, the amount is 1+(−3)+4=2.

输入

The first line contains one integer t (1≤t≤104) — the number of test cases. Then t test cases follow.

The first line of each test case consists of two positive integers n, m (1≤n,m≤2⋅105) — the number of numbers on the disk and the number of asked questions.

The second line of each test case contains n integers a1,a2,…,an (−109≤ai≤109).

The third line of each test case contains m positive integers x1,x2,…,xm (1≤x≤109).

It is guaranteed that the sums of n and m over all test cases do not exceed 2⋅105.

输出

Print m numbers on a separate line for each test case. The i-th number is:

1.−1 if the drive will run infinitely;
2.the number of seconds the drive will run, otherwise.

样例

input
3
3 3
1 -3 4
1 5 2
2 2
-2 0
1 2
2 2
0 1
1 2
output
0 6 2
-1 -1
1 3

题目大意

有一个循环数组,周期为n,有m次询问,每次询问给出一个x,需要输出第一个前缀和 ≥ x 的 位置。

思路

首先,失败的情况 ,查询的x大于一圈前缀和的最大值,并且一圈的前缀和小于0。
成功的情况,二分查找找答案,对于在一圈能找到答案的就直接找就可以,对于不在一圈里的答案,我们要循环 上取整((x-最大值)/ sum(一圈的和)),一定要先减再除,比如3 -2 2 -1 最大前缀和为3,一圈的前缀和为2,我们查4,如果不先减再除,就得出转两圈整,但是其实转一圈,再移动一次就可以,为5,所以说 先减再除

二分我们要维护一个非递减数列,因为一圈里在前缀和最大值后边的前缀和是无效的,所以我们将后边的更新为最大值,需要总店理解一下

代码

#include <iostream>
#include <cmath>

using namespace std;

typedef long long ll;

const int N = 1e6 + 10;

ll a[N],b[N];

int main()
{
	int T;
	cin >> T;
	
	while(T --)
	{
		int n,m;
		cin >> n >> m;
		
		ll sum = 0,MAX = 0;
		for(int i = 1;i <= n;i ++)
		{
			cin >> a[i];
			sum += a[i];
			
			MAX = max(MAX,sum);
			b[i] = MAX;
		}
		
		for(int k = 0;k < m;k ++)
		{
			ll x;
			cin >> x;
			
			if(x > MAX && sum <= 0) cout << "-1" << " ";
			else if(x <= MAX)
			{
				int ans = lower_bound(b,b + n,x) - b - 1;
				cout << ans << " ";
			}
			else
			{
				ll ans = -1;
				ll k = ceil((x - MAX) * 1.0 / sum);
				ans += n * k;
				x -= k * sum;
				ans += lower_bound(b,b + n,x) - b;
				cout << ans << " ";
			}
		}
		
		puts("");
	}
	
	return 0;
}

这个题扣了得有一个半小时,蛮难理解的,主要是找>=的值,就很巧妙
我太菜了(

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

半碗无糖蓝莓冻

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

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

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

打赏作者

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

抵扣说明:

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

余额充值