Codeforces Round #834 [CF1759] A-D 题解

目录

  • A(Yes-Yes?)
    • 题面翻译
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 题目分析
    • 正解代码
  • B(Lost Permutation)
    • 题面翻译
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 题目分析
    • 正解代码
  • C(Thermostat)
    • 题面翻译
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 题目分析
    • 正解代码
  • D(Make It Round)
    • 题面翻译
    • 输入格式
    • 输出格式
    • 样例解释
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 题目分析
    • 正解代码

A(Yes-Yes?)

题面翻译

给定 t t t 个字符串,请判定这些字符串是否分别是 YesYesYesYes … \texttt{YesYesYesYes\dots} YesYesYesYes 的子串。是则输出 YES,否则输出 NOYESNO 大小写不定)。

Translated by @JYqwq

样例 #1

样例输入 #1

12
YES
esYes
codeforces
es
se
YesY
esYesYesYesYesYesYe
seY
Yess
sY
o
Yes

样例输出 #1

NO
YES
NO
YES
NO
YES
YES
NO
NO
YES
NO
YES

题目分析

众所不一定周知,有个函数,叫做find()。其作用就是在某个字符串中寻找其子串。例如x.find(y)!=string::npos,这个表示在字符串 x x x 中寻找 y y y,且结果存在于 x x x 中,即 y y y x x x 的子串。那么,我们只需要判断一下是不是 Y e s Y e s Y e s . . . YesYesYes... YesYesYes... 的子串即可。

正解代码

#include
using namespace std;
int t;
string s="YesYesYesYesYesYesYesYesYesYesYesYesYesYesYesYesYesYesYesYes";
int main()
{
	//freopen("A.in","r",stdin);
	//freopen("A.out","w",stdout);
	cin>>t;
	while(t--)
	{
		string a;
		cin>>a;
		if(s.find(a)!=string::npos)
		{
			cout<<"YES\n";
		}
		else
		{
			cout<<"NO\n";
		}
	}
}

B(Lost Permutation)

题面翻译

t t t 组输入。

对于每组输入,第一行是 m , s m,s m,s,第二行是 b 1 , b 2 , … , b m b_1,b_2,\dots,b_m b1,b2,,bm

已知原数组 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,,an 1 ∼ n 1\sim n 1n 的一个排列。现在去掉的一些数,变成了 b 1 , b 2 , … , b m b_1,b_2,\dots,b_m b1,b2,,bm,去掉的数字的和为 s s s。问能否求出一个 a a a(能则 YES,否则 NO,大小写不敏感)。

样例 #1

样例输入 #1

5
3 13
3 1 4
1 1
1
3 3
1 4 2
2 1
4 3
5 6
1 2 3 4 5

样例输出 #1

YES
NO
YES
NO
YES

题目分析

由于 b b b 中最大的数一定在 a a a 中出现,所以这个排列最小的总和为 b b b 中所有元素之和。然后,与 s s s 进行比较即可。

正解代码

#include
using namespace std;
int t;
int m,s;
int a[100000];
int main()
{
	//freopen("B.in","r",stdin);
	//freopen("B.out","w",stdout);
	cin>>t;
	while(t--)
	{
		int maxx=0;
		int sum=0;
		cin>>m>>s;
		for(int i=1;i<=m;i++)
		{
			cin>>a[i];
			sum+=a[i];
			maxx=max(maxx,a[i]);
		}
		int ans=(1+maxx)*maxx/2-sum;
		if(ans>s)
		{
			cout<<"NO\n";
		}
		else
		{
			bool bo=0;
			int k=maxx+1;
			while(ans<=s)
			{
				if(ans==s)
				{
					cout<<"YES\n";
					bo=1;
					break;
				}
				else
				{
					ans+=k;
					k++;		
				}
			}
			if(bo==0)
			{
				cout<<"NO\n";
			}
		}
	}
	return 0;
}

C(Thermostat)

题面翻译

t t t 组输入。

对于每组输入,有五个整数 l , r , x , a , b l,r,x,a,b l,r,x,a,b

对于一个 p p p 的操作,可以从 p p p 变成 q q q,但是要保证 ∣ p − q ∣ ≥ x |p-q|\ge x pqx l ≤ q ≤ r l\le q\le r lqr

问从 a a a b b b 需要的最少操作数,若不能到 b b b 输出 -1(题目保证 l ≤ a , b ≤ r l\le a,b \le r la,br)。

Translated by @JYqwq

样例 #1

样例输入 #1

10
3 5 6
3 3
0 15 5
4 5
0 10 5
3 7
3 5 6
3 4
-10 10 11
-5 6
-3 3 4
1 0
-5 10 8
9 2
1 5 1
2 5
-1 4 3
0 2
-6 3 6
-1 -4

样例输出 #1

0
2
3
-1
1
-1
3
1
3
-1

题目分析

首先,有三种需要特判的情况:

  1. a = b a=b a=b 时:
    无需操作,答案为 0 0 0
  2. ∣ a − b ∣ ≥ x |a-b|≥x abx 时:
    一次操作即可,答案为 1 1 1
  3. ∣ l − b ∣ < x |l-b|lb<x 并且 ∣ r − b ∣ < x |r-b|rb<x 时:
    不可能成功,答案为 − 1 -1 1
    然后,我们就需要考虑操作的问题了。为了能使操作进行, ∣ a − b ∣ |a-b| ab 的值要尽量的大。所以,我们不妨先把 a a a 的值移到边界 l , r l,r l,r 上,判断此时能否触发条件进行操作,将其值调整到 b b b 上,如果能,答案为 2 2 2;否则跳到另一端的边界上,再次判断能否在这端的边界将其值调整为 b b b,如果能,答案为 3 3 3;否则不更新答案。

最后,如果如果怎么调整都无法满足条件,则答案为 − 1 -1 1

正解代码

#include
#define int long long
using namespace std;
int t;
int l,r;
int x,a,b;
signed main()
{
	//freopen("C.in","r",stdin);
	//freopen("C.out","w",stdout);
	cin>>t;
	while(t--)
	{
		int k=1e5;
		cin>>l>>r>>x>>a>>b;
		if(a==b)
		{
			cout<<0<<"\n";
			continue;
		}
		if(abs(a-b)>=x)
		{
			cout<<1<<"\n";
			continue;
		}
		if(abs(l-b)<x&&abs(r-b)<x)
		{
			cout<<-1<<"\n";
			continue;
		}
		if(abs(l-a)>=x)
		{
			if(abs(l-b)>=x)
			{
				k=2;
			}
			else{
				k=3;
			}
		}
		if(abs(r-a)>=x)
		{
			if(abs(r-b)>=x)
			{
				k=2;
			}
			else
			{
				k=k<3?k:3;
			}
		}			
		if(k>3)
		{
			cout<<-1<<"\n";
		}
		else 
		{
			cout<<k<<'\n';
		}
	}
	return 0;
}

D(Make It Round)

题面翻译

给定 n n n m m m, 我们可以把 n n n 变为 n ⋅ k ( 1 ≤ k ≤ m , k ∈ N ∗ ) n\cdot k(1\leq k\leq m,k∈N^{*}) nk(1km,kN), 请输出末尾 0 0 0 的个数最多的 n ⋅ k n\cdot k nk

  • 例如, 481000 481000 481000 1000010 1000010 1000010 末尾 0 0 0 的个数更多。
  • 如果有多个末尾 0 0 0 个数最多的 n ⋅ k n\cdot k nk, 则输出其中最大的一个。
  • 如果不存在末尾 0 0 0 个数更多的 n ⋅ k n\cdot k nk, 则输出 n ⋅ m n\cdot m nm

输入格式

第一行输入一个整数 t   ( 1 ≤ t ≤ 1 0 4 ) t\ (1\leq t \leq 10^4) t (1t104), 表示数据组数。
之后的 t t t 行,每行包含两个整数 n n n, m   ( 1 ≤ n , m ≤ 1 0 9 ) m\ (1\leq n,m \leq 10^9) m (1n,m109)

输出格式

对于每组数据,输出末尾 0 0 0 的个数最多的 n ⋅ k   ( 1 ≤ k ≤ m , k ∈ N ∗ ) n\cdot k\ (1\leq k\leq m,k∈N^{*}) nk (1km,kN)

如果有多个末尾 0 0 0 个数最多的 n ⋅ k n\cdot k nk, 则输出其中最大的一个。

如果不存在末尾 0 0 0 个数更多的 n ⋅ k n\cdot k nk, 则输出 n ⋅ m n\cdot m nm

样例解释

在第一组数据中 n = 6 , m = 11 n=6,m=11 n=6,m=11, 我们无法得到一个末尾有两个 0 0 0 的数,因此我们令 k = 10 k=10 k=10, 输出 6 ⋅ 10 = 60 6\cdot 10=60 610=60。(它的末尾有 1 1 1 0 0 0, 且它比 30 30 30 更大)

在第三组数据中 n = 13 , m = 5 n=13,m=5 n=13,m=5, 所有可能的 n ⋅ k n\cdot k nk 末尾都没有 0 0 0, 因此我们输出 n ⋅ m = 65 n\cdot m=65 nm=65

样例 #1

样例输入 #1

10
6 11
5 43
13 5
4 16
10050 12345
2 6
4 30
25 10
2 81
1 7

样例输出 #1

60
200
65
60
120600000
10
100
200
100
7

题目分析

背过九九乘法表的都知道 10 = 2 × 5 10=2×5 10=2×5,所以某个数字有多少个 0 0 0 就相当于有多少个 2 × 5 2×5 2×5 啦。我们设剩下的乘积为 x x x,则我们只需要在 [ 1 , m ] [1,m] [1,m] 中找到 x x x 的最大的倍数,也就是 ⌊ m / x ⌋ × x ⌊ m/x⌋×x m/x×x(不会打分数线),然后乘以原来的那个数即可。

正解代码

#include
#define int long long
using namespace std;
int t;
int n,m;
signed main()
{
	//freopen("D.in","r",stdin);
	//freopen("D.out","w",stdout);
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		for(int i=18;i>=0;i--)
		{
			int s=n;
			int x=i,y=i;
			int sum=1;
			while(s%2==0&&s>0)	
			{
				s/=2;
				x--;	
			}
			while(s%5==0&&s>0)	
			{
				s/=5;
				y--;
			}
			while(x>0)	
			{
				sum*=2;
				x--;
			}
			while(y>0)
			{
				sum*=5;
				y--;
			}
			if(sum<=m)
			{
				int X=m/sum*sum;
				cout<<n*X<<endl;
				break;
			}
		}
	}
	return 0;
}

你可能感兴趣的:(洛谷,c++,算法)