国庆练习5

Phone Numbers CF 1060A

Description

Let's call a string a phone number if it has length 11 and fits the pattern "8xxxxxxxxxx", where each "x" is replaced by a digit.

For example, "80123456789" and "80000000000" are phone numbers, while "8012345678" and "79000000000" are not.

You have nn cards with digits, and you want to use them to make as many phone numbers as possible. Each card must be used in at most one phone number, and you don't have to use all cards. The phone numbers do not necessarily have to be distinct.

Input

The first line contains an integer nn — the number of cards with digits that you have (1n1001≤n≤100).

The second line contains a string of nn digits (characters "0", "1", ..., "9") s1,s2,,sns1,s2,…,sn. The string will not contain any other characters, such as leading or trailing spaces.

Output

If at least one phone number can be made from these cards, output the maximum number of phone numbers that can be made. Otherwise, output 0.

Sample Input

Input
11 
00000000008
Output
1
Input
22 
0011223344556677889988
Output
2
Input
11 
31415926535
Output
0

Hint

In the first example, one phone number, "8000000000", can be made from these cards.

In the second example, you can make two phone numbers from the cards, for example, "80123456789" and "80123456789".

In the third example you can't make any phone number from the given cards.

题目意思:给你长度为n个数字字符串,求出能够组合成多少个电话号码。每一个数字都只能使用一次,电话号必须是8开头,长度为11。

解题思路:数字字符串的长度和8的数量决定了能构成的电话号码的个数。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<map>
 4 #include<algorithm>
 5 using namespace std;
 6 char s[110];
 7 int main()
 8 {
 9     int n,i,counts,a,ans;
10     scanf("%d",&n);
11     counts=0;
12     a=0;
13     getchar();
14     gets(s);
15     for(i=0;i<n;i++)
16     {
17         if(s[i]=='8')
18         {
19             counts++;
20         }
21     }
22     a=n/11;
23     ans=min(a,counts);
24     printf("%d\n",ans);
25     return 0;
26 }

 

 Maximum Sum of Digits CF 1060B

 

Description

You are given a positive integer nn.

Let S(x)S(x) be sum of digits in base 10 representation of xx, for example, S(123)=1+2+3=6, S(0)=0

Your task is to find two integers a,ba,b, such that 0a,bn, a+b=n and S(a)+S(b) is the largest possible among all such pairs.

Input

The only line of input contains an integer nn (1n1012)

Output

Print largest S(a)+S(b) among all pairs of integers a,ba,b, such that 0a,bnand a+b=n.

Sample Input

Input
35
Output
17
Input
10000000000
Output
91

Hint

In the first example, you can choose, for example, a=17and b=18, so that S(17)+S(18)=1+7+1+8=17. It can be shown that it is impossible to get a larger answer.

In the second test example, you can choose, for example, a=5000000001and b=4999999999, with S(5000000001)+S(4999999999)=91. It can be shown that it is impossible to get a larger answer.

 

题目意思:给你一个n,将n拆成两个数a和b,并且s(a)+s(b)最大,s(123)=1+2+3,输出s(a)+s(b)

解题思路:这一道题又是一道构造的题目,对于构造类型的题目,我们需要找到一个特性的东西来表达共性。我们很容易想到,当拆分的两个数中9的数量最多的时候,s(a)+s(b)最大,例如35=29+6=19+16=9+26=17+18,我们发现他们的s(a)+s(b)都等于17;

又比如 10000000000,我们可以拆成 10000000000=9999999999+1=9999999998+2...,他们的s(a)+s(b)都等于91

所以我们可以从最高位拆分,比如23456=19999+3457,100=99+1,123=99+24这种形式,这时获得的9是最多的,s(a)+s(b)也是最大的

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<map>
 4 #include<algorithm>
 5 #define ll long long int
 6 using namespace std;
 7 ll getsum(ll x)///拆分得到s函数
 8 {
 9     ll s=0;
10     while(x!=0)
11     {
12         s+=x%10;
13         x=x/10;
14     }
15     return s;
16 }
17 int main()
18 {
19     ll n,a,b,ans,t,m;
20     ans=0;
21     scanf("%lld",&n);
22     t=n;
23     m=1;
24     while(t>10)///找到最高位
25     {
26         t=t/10;
27         m=m*10;
28     }
29     a=t*m-1;///第一部分
30     b=n-a;///第二部分
31     ans+=getsum(a);
32     ans+=getsum(b);
33     printf("%lld\n",ans);
34     return 0;
35 }

 

 Memory and Trident CF 712B

 

Description

Memory is performing a walk on the two-dimensional plane, starting at the origin. He is given a string s with his directions for motion:

  • An 'L' indicates he should move one unit left.
  • An 'R' indicates he should move one unit right.
  • A 'U' indicates he should move one unit up.
  • A 'D' indicates he should move one unit down.

But now Memory wants to end at the origin. To do this, he has a special trident. This trident can replace any character in s with any of 'L', 'R', 'U', or 'D'. However, because he doesn't want to wear out the trident, he wants to make the minimum number of edits possible. Please tell Memory what is the minimum number of changes he needs to make to produce a string that, when walked, will end at the origin, or if there is no such string.

 

Input

The first and only line contains the string s (1 ≤ |s| ≤ 100 000) — the instructions Memory is given.

 

Output

If there is a string satisfying the conditions, output a single integer — the minimum number of edits required. In case it's not possible to change the sequence in such a way that it will bring Memory to to the origin, output -1.

 

Sample Input

Input
RRU
Output
-1
Input
UDUR
Output
1
Input
RUUR
Output
2

 

Hint

In the first sample test, Memory is told to walk right, then right, then up. It is easy to see that it is impossible to edit these instructions to form a valid walk.

In the second sample test, Memory is told to walk up, then down, then up, then right. One possible solution is to change s to "LDUR". This string uses 1 edit, which is the minimum possible. It also ends at the origin.

题目意思:L向左走,R向右走,U向上走,D向下走,通过最少数量的改变使主人公从原点出发再次回到原点。

解题思路:我们知道要想回到原点,向上的次数必然等于向下的次数,向左的次数必然等于向右的次数。统计原来字符串中上下左右的次数,上下抵消,左右抵消,剩下的汇总除以2即为最小改变量。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<map>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define ll long long int
 7 char s[100010];
 8 using namespace std;
 9 int main()
10 {
11     int i,len,ans;
12     int a,b,c,d;
13     int x,y;
14     a=0,b=0,c=0,d=0;
15     gets(s);
16     len=strlen(s);
17     if(len%2)
18     {
19         printf("-1\n");
20     }
21     else
22     {
23         for(i=0; i<len; i++)
24         {
25             if(s[i]=='U')
26             {
27                 a++;
28             }
29             else if(s[i]=='D')
30             {
31                 b++;
32             }
33             else if(s[i]=='R')
34             {
35                 c++;
36             }
37             else if(s[i]=='L')
38             {
39                 d++;
40             }
41         }
42         x=fabs(a-b);
43         y=fabs(c-d);
44         if((x+y)%2)
45         {
46             printf("-1\n");
47         }
48         else
49         {
50             printf("%d\n",(x+y)/2);
51         }
52     }
53     return 0;
54 }

 

 

 

Memory and De-Evolution  CF 712C

 

Description

Memory is now interested in the de-evolution(演化) of objects, specifically triangles(三角形). He starts with an equilateral triangle of side length x, and he wishes to perform operations to obtain an equilateral triangle of side length y.

In a single second, he can modify the length of a single side of the current triangle such that it remains a non-degenerate triangle (triangle of positive area). At any moment of time, the length of each side should be integer.

What is the minimum number of seconds required for Memory to obtain the equilateral triangle of side length y?

Input

The first and only line contains two integers x and y (3 ≤ y < x ≤ 100 000) — the starting and ending equilateral triangle side lengths respectively.

Output

Print a single integer — the minimum number of seconds required for Memory to obtain the equilateral triangle of side length y if he starts with the equilateral triangle of side length x.

Sample Input

Input
6 3
Output
4
Input
8 5
Output
3
Input
22 4
Output
6

Hint

In the first sample test, Memory starts with an equilateral triangle of side length 6 and wants one of side length 3. Denote a triangle with sides a, b, and c as (a, b, c). Then, Memory can do .

In the second sample test, Memory can do .

In the third sample test, Memory can do:

.

 

题目意思:给你一个边长为x的等边三角形,每一次可以改变某一边的长度,但改变后仍然可以构成三角形,问至少需要变化多少次就能变成边长为y的等边三角形。

解题思路:我们知道三角形三边存在着这样的关系:任意两边之和大于第三边,任意两边之差小于第三边。我们可以先从边长较小的等边三角形出发,将它变为目标中那个边长较大的等边三角形。而为了变化的次数最少,我们必然每一次变化都要在符合要求的情况下变化最大,策略就是贪心!

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<map>
 4 #include<algorithm>
 5 #define ll long long int
 6 using namespace std;
 7 int main()
 8 {
 9     int x,y;
10     int a,b,c,ans,flag;
11     scanf("%d%d",&x,&y);
12     flag=1;
13     ans=0;
14     a=y,b=y,c=y;
15     while(1)
16     {
17 
18         if(a==x&&b==x&&c==x)
19         {
20             break;
21         }
22         if(flag%3==1)
23         {
24             flag++;
25             a=b+c-1;
26             ans++;
27             if(a>=x)
28             {
29                 break;
30             }
31         }
32         else if(flag%3==2)
33         {
34             flag++;
35             b=a+c-1;
36             ans++;
37             if(b>=x)
38             {
39                 break;
40             }
41         }
42         else if(flag%3==0)
43         {
44             flag++;
45             c=a+b-1;
46             ans++;
47             if(c>=x)
48             {
49                 break;
50             }
51         }
52     }
53     printf("%d\n",ans+2);///某一边变化成功了,还有另外的两条边
54     return 0;
55 }

 

 

转载于:https://www.cnblogs.com/wkfvawl/p/9746955.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值