Educational Codeforces Round 99 A到E题解

链接 https://codeforces.com/contest/1455

A. Strange Functions

Let’s define a function f(x) (x is a positive integer) as follows: write all digits of the decimal representation of x backwards, then get rid of the leading zeroes. For example, f(321)=123, f(120)=21, f(1000000)=1, f(111)=111.

Let’s define another function g(x)=xf(f(x)) (x is a positive integer as well).

Your task is the following: for the given positive integer n, calculate the number of different values of g(x) among all numbers x such that 1≤x≤n.

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

Each test case consists of one line containing one integer n (1≤n<10100). This integer is given without leading zeroes.

Output
For each test case, print one integer — the number of different values of the function g(x), if x can be any integer from [1,n].

Example
input
5
4
37
998244353
1000000007
12345678901337426966631415
output
1
2
9
10
26
Note
Explanations for the two first test cases of the example:

if n=4, then for every integer x such that 1≤x≤n, xf(f(x))=1;
if n=37, then for some integers x such that 1≤x≤n, xf(f(x))=1 (for example, if x=23, f(f(x))=23,xf(f(x))=1); and for other values of x, xf(f(x))=10 (for example, if x=30, f(f(x))=3, xf(f(x))=10). So, there are two different values of g(x).

题意
简单题,不说了

思路
输出长度就行了

代码

#include <bits/stdc++.h>
typedef long long ll;
const ll mod = 1e9+7;
using namespace std;
namespace fastIO {
    inline ll qpow(ll a, ll b) {
        ll ans = 1, base = a;
        while (b) {
            if (b & 1) ans = (ans * base % mod +mod )%mod;
            base = (base * base % mod + mod)%mod;
            b >>= 1;
        }
        return ans;
    }
}
using namespace fastIO;
const int N = 1e6 + 5;
int Case,n,len; 
char s[N];
int main(){
	Case=1;
	scanf("%d",&Case);
	while(Case--){
		scanf("%s",s+1);
		printf("%d\n",strlen(s+1));
 	}
	return 0;
}

B. Jumps
You are standing on the OX-axis at point 0 and you want to move to an integer point x>0.

You can make several jumps. Suppose you’re currently at point y (y may be negative) and jump for the k-th time. You can:

either jump to the point y+k
or jump to the point y−1.
What is the minimum number of jumps you need to reach the point x?

Input
The first line contains a single integer t (1≤t≤1000) — the number of test cases.

The first and only line of each test case contains the single integer x (1≤x≤106) — the destination point.

Output
For each test case, print the single integer — the minimum number of jumps to reach x. It can be proved that we can reach any integer point x.

Example
input
5
1
2
3
4
5
output
1
3
2
3
4
Note
In the first test case x=1, so you need only one jump: the 1-st jump from 0 to 0+1=1.

In the second test case x=2. You need at least three jumps:

the 1-st jump from 0 to 0+1=1;
the 2-nd jump from 1 to 1+2=3;
the 3-rd jump from 3 to 3−1=2;
Two jumps are not enough because these are the only possible variants:

the 1-st jump as −1 and the 2-nd one as −1 — you’ll reach 0−1−1=−2;
the 1-st jump as −1 and the 2-nd one as +2 — you’ll reach 0−1+2=1;
the 1-st jump as +1 and the 2-nd one as −1 — you’ll reach 0+1−1=0;
the 1-st jump as +1 and the 2-nd one as +2 — you’ll reach 0+1+2=3;
In the third test case, you need two jumps: the 1-st one as +1 and the 2-nd one as +2, so 0+1+2=3.

In the fourth test case, you need three jumps: the 1-st one as −1, the 2-nd one as +2 and the 3-rd one as +3, so 0−1+2+3=4.

题意
我们能对一个数进行两种操作:
第一种是在第i次操作减一
第二种是在第i次操作加i
现在给你一个数,求最少操作次数能到这个数?

思路
思维题,我们看样例发现
求在1+2+3+…+n哪个区间内,输出i值即可,如果这个数是这个数列和减一的话,则我们要加一次操作,观察可推出。
比如说
1 + 2 + 3 + 4 = 10
9的话只能1 + 2 + 3 + 4 - 1可得,其他区间内的数都能改变其中项为-1实现。

代码

#include <bits/stdc++.h>
typedef long long ll;
const ll mod = 1e9+7;
using namespace std;
namespace fastIO {
    inline ll qpow(ll a, ll b) {
        ll ans = 1, base = a;
        while (b) {
            if (b & 1) ans = (ans * base % mod +mod )%mod;
            base = (base * base % mod + mod)%mod;
            b >>= 1;
        }
        return ans;
    }
}
using namespace fastIO;
const int N = 1e6 + 5;
int Case,n;
int f[N]; 
int cnt;
void init(){
	for(int i=0;i<=N;i++){
		int t=(i*i+i)/2;
		if(t>N) break;
		f[cnt++]=t;
	}
}
int main(){
	Case=1;
	init();
	cout<<endl;
	scanf("%d",&Case);
	while(Case--){
		scanf("%d",&n);
		int vis;
		for(int i=1;i<=cnt;i++){
			if(f[i]>=n){
				vis = i;
				break;
			} 
		}
		if(f[vis]-1==n) printf("%d\n",vis+1);
		else printf("%d\n",vis);
	
 	}
	return 0;
}

C. Ping-pong
Alice and Bob play ping-pong with simplified rules.

During the game, the player serving the ball commences a play. The server strikes the ball then the receiver makes a return by hitting the ball back. Thereafter, the server and receiver must alternately make a return until one of them doesn’t make a return.

The one who doesn’t make a return loses this play. The winner of the play commences the next play. Alice starts the first play.

Alice has x stamina and Bob has y. To hit the ball (while serving or returning) each player spends 1 stamina, so if they don’t have any stamina, they can’t return the ball (and lose the play) or can’t serve the ball (in this case, the other player serves the ball instead). If both players run out of stamina, the game is over.

Sometimes, it’s strategically optimal not to return the ball, lose the current play, but save the stamina. On the contrary, when the server commences a play, they have to hit the ball, if they have some stamina left.

Both Alice and Bob play optimally and want to, firstly, maximize their number of wins and, secondly, minimize the number of wins of their opponent.

Calculate the resulting number of Alice’s and Bob’s wins.

Input
The first line contains a single integer t (1≤t≤104) — the number of test cases.

The first and only line of each test case contains two integers x and y (1≤x,y≤106) — Alice’s and Bob’s initial stamina.

Output
For each test case, print two integers — the resulting number of Alice’s and Bob’s wins, if both of them play optimally.

Example
input
3
1 1
2 1
1 7
output
0 1
1 1
0 7
Note
In the first test case, Alice serves the ball and spends 1 stamina. Then Bob returns the ball and also spends 1 stamina. Alice can’t return the ball since she has no stamina left and loses the play. Both of them ran out of stamina, so the game is over with 0 Alice’s wins and 1 Bob’s wins.

In the second test case, Alice serves the ball and spends 1 stamina. Bob decides not to return the ball — he loses the play but saves stamina. Alice, as the winner of the last play, serves the ball in the next play and spends 1 more stamina. This time, Bob returns the ball and spends 1 stamina. Alice doesn’t have any stamina left, so she can’t return the ball and loses the play. Both of them ran out of stamina, so the game is over with 1 Alice’s and 1 Bob’s win.

In the third test case, Alice serves the ball and spends 1 stamina. Bob returns the ball and spends 1 stamina. Alice ran out of stamina, so she can’t return the ball and loses the play. Bob, as a winner, serves the ball in the next 6 plays. Each time Alice can’t return the ball and loses each play. The game is over with 0 Alice’s and 7 Bob’s wins.

题意
给你双方耐力值,每次发球接球都会减一耐力值,Alice先发球,问两边能最多赢多少次。

思路
简单博弈论,Bob一直不接球直到Alice就1耐力值时就行,所以只要输出Alice的耐力值减一,注意0的时候特判,另一方直接输出就行,A题难度…
数据范围1到1e6,行吧…
代码

#include <bits/stdc++.h>
typedef long long ll;
const ll mod = 1e9+7;
using namespace std;
namespace fastIO {
    inline void input(int& res) {
        char c = getchar();res = 0;int f = 1;
        while (!isdigit(c)) { f ^= c == '-'; c = getchar(); }
        while (isdigit(c)) { res = (res << 3) + (res << 1) + (c ^ 48);c = getchar(); }
        res = f ? res : -res;
    }
    inline ll qpow(ll a, ll b) {
        ll ans = 1, base = a;
        while (b) {
            if (b & 1) ans = (ans * base % mod +mod )%mod;
            base = (base * base % mod + mod)%mod;
            b >>= 1;
        }
        return ans;
    }
}
using namespace fastIO;
const int N = 1e6 + 5;
int Case,a,b; 
void solve(){
	scanf("%d %d",&a,&b);
	printf("%d %d\n",a==0?0:a-1,b);
}
int main(){
	Case=1;
	scanf("%d",&Case);
	while(Case--){
		solve();
 	}
	return 0;
}

D. Sequence and Swaps
You are given a sequence a consisting of n integers a1,a2,…,an, and an integer x. Your task is to make the sequence a sorted (it is considered sorted if the condition a1≤a2≤a3≤⋯≤an holds).

To make the sequence sorted, you may perform the following operation any number of times you want (possibly zero): choose an integer i such that 1≤i≤n and ai>x, and swap the values of ai and x.

For example, if a=[0,2,3,5,4], x=1, the following sequence of operations is possible:

choose i=2 (it is possible since a2>x), then a=[0,1,3,5,4], x=2;
choose i=3 (it is possible since a3>x), then a=[0,1,2,5,4], x=3;
choose i=4 (it is possible since a4>x), then a=[0,1,2,3,4], x=5.
Calculate the minimum number of operations you have to perform so that a becomes sorted, or report that it is impossible.

Input
The first line contains one integer t (1≤t≤500) — the number of test cases.

Each test case consists of two lines. The first line contains two integers n and x (1≤n≤500, 0≤x≤500) — the number of elements in the sequence and the initial value of x.

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

The sum of values of n over all test cases in the input does not exceed 500.

Output
For each test case, print one integer — the minimum number of operations you have to perform to make a sorted, or −1, if it is impossible.

Example
input
6
4 1
2 3 5 4
5 6
1 1 3 4 4
1 10
2
2 10
11 9
2 10
12 11
5 18
81 324 218 413 324
output
3
0
0
-1
1
3

题意
给你一个序列和x,每次可以将序列中一个比x的数和x交换,问你最少操作次数,时序列升序排序,如果不可能输出-1。

思路
模拟,我们可以用一个新数组复制一下,将x插入,对他进行排序,这样我们知道排序结果,然后我们反推次数,如果交换之后还不能升序,这种肯定是不可能的,注意的是,有些情况下我们不用严格按照排序后的序列排序,因为我们可能某次操作后已经满足了。
例如
5 3
1 2 5 3 6

代码

#include <bits/stdc++.h>
typedef long long ll;
const ll mod = 1e9+7;
namespace fastIO {
    inline void input(int& res) {
        char c = getchar();res = 0;int f = 1;
        while (!isdigit(c)) { f ^= c == '-'; c = getchar(); }
        while (isdigit(c)) { res = (res << 3) + (res << 1) + (c ^ 48);c = getchar(); }
        res = f ? res : -res;
    }
    inline ll qpow(ll a, ll b) {
        ll ans = 1, base = a;
        while (b) {
            if (b & 1) ans = (ans * base % mod +mod )%mod;
            base = (base * base % mod + mod)%mod;
            b >>= 1;
        }
        return ans;
    }
}
using namespace fastIO;
using namespace std;
const int N = 1e3 + 5;
int Case,n,x; 
int a[N],aa[N];
bool check(int x){
	for(int i=x;i<=n;i++){
		if(a[i]<a[i-1]) return false;
	}
	return true;
}
int main(){
	Case=1;
	scanf("%d",&Case);
	while(Case--){
		bool flag = true;
		bool f = true;
		scanf("%d %d",&n,&x);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			if(a[i]<a[i-1]) f=false;
			aa[i]=a[i];
		}
		aa[n+1]=x;
		sort(aa+1,aa+n+1+1);
		int cnt = 0;
		for(int i=1;i<=n;i++){
			if(a[i]==aa[i]);
			else{
				if(a[i]>x){
					swap(a[i],x);
					cnt++;
				}
				else
					flag = false;
				if(a[i]<a[i-1]) flag = false;
			}
			if(check(i)) break;
		}
		if(f) printf("0\n");
		else
			printf("%d\n",flag?cnt:-1);
 	}
	return 0;
}

E. Four Points
You are given four different integer points p1, p2, p3 and p4 on XY grid.

In one step you can choose one of the points pi and move it in one of four directions by one. In other words, if you have chosen point pi=(x,y) you can move it to (x,y+1), (x,y−1), (x+1,y) or (x−1,y).

Your goal to move points in such a way that they will form a square with sides parallel to OX and OY axes (a square with side 0 is allowed).

What is the minimum number of steps you need to make such a square?

Input
The first line contains a single integer t (1≤t≤104) — the number of test cases.

Each test case consists of four lines. Each line contains two integers x and y (0≤x,y≤109) — coordinates of one of the points pi=(x,y).

All points are different in one test case.

Output
For each test case, print the single integer — the minimum number of steps to make a square.

Example
input
3
0 2
4 2
2 0
2 4
1 0
2 0
4 0
6 0
1 6
2 2
2 5
4 1
output
8
7
5
Note
In the first test case, one of the optimal solutions is shown below:

Each point was moved two times, so the answer 2+2+2+2=8.
In the secon在这里插入图片描述
d test case, one of the optimal solutions is shown below:
在这里插入图片描述

The answer is 3+1+0+3=7.
In the third test case, one of the optimal solutions is shown below:
在这里插入图片描述

The answer is 1+1+2+1=5.

题意
给你四个点,问你最少操作次数,使四个点构成一个正方形。

思路
我们可以通过暴力枚举来做,我们发现我们可以将两个点固定,横坐标或纵坐标的差来确定正方形边长,然后我们求步数,求最小值。
难就难在求步数上,我们将x的1 3固定,y的1 2固定,这样我们每次减去正方形边长后排序,
通过x4 + x3 - x2 - x1 + y4 +y3 - y2 - y1来求步数

代码

#include <bits/stdc++.h>
typedef long long ll;
const ll mod = 9999999967;
using namespace std;
namespace fastIO {
    inline void input(int& res) {
        char c = getchar();res = 0;int f = 1;
        while (!isdigit(c)) { f ^= c == '-'; c = getchar(); }
        while (isdigit(c)) { res = (res << 3) + (res << 1) + (c ^ 48);c = getchar(); }
        res = f ? res : -res;
    }
    inline ll qpow(ll a, ll b) {
        ll ans = 1, base = a;
        while (b) {
            if (b & 1) ans = (ans * base % mod +mod )%mod;
            base = (base * base % mod + mod)%mod;
            b >>= 1;
        }
        return ans;
    }
}
using namespace fastIO;
const int N = 1e6 + 5;

int Case;
struct node{
	ll x;
	ll y;
}zr[5];

int cnt[5];
ll x[5],xx[5],y[5],yy[5];

ll cal(ll d){
	for(int i=1;i<=4;i++){
		xx[i]=x[i],yy[i]=y[i];
	}
	xx[2]-=d,xx[4]-=d,yy[3]-=d,yy[4]-=d;
	sort(xx+1,xx+4+1),sort(yy+1,yy+4+1);
	return xx[4]+xx[3]-xx[2]-xx[1]+yy[4]+yy[3]-yy[2]-yy[1];
}

void solve(){
	for(int i=1;i<=4;i++){
		cnt[i]=i;
		scanf("%lld %lld",&zr[i].x,&zr[i].y);
	}
	ll res = 1e18;
	do{	
		for(int i=1;i<=4;i++){
			x[i]=zr[cnt[i]].x,y[i]=zr[cnt[i]].y;
		}
		res = min(res,cal(x[2]-x[1]));
		res = min(res,cal(x[2]-x[3]));
		res = min(res,cal(x[4]-x[1]));
		res = min(res,cal(x[4]-x[3]));
		res = min(res,cal(y[3]-y[1]));
		res = min(res,cal(y[3]-y[2]));
		res = min(res,cal(y[4]-y[1]));
		res = min(res,cal(y[4]-y[2]));
	}while(next_permutation(cnt+1,cnt+4+1));
	printf("%lld\n",res);
}

int main(){
	Case=1;
	input(Case);
	while(Case--){
		solve();
 	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值