Codeforces Round #570 (Div. 3) B. Equalize Prices、C. Computer Game、D. Candy Box (easy version)、E. Subsequences (easy version)

B题题意:

给你n个物品的价格,你需要找出来一个值b,使得每一个物品与这个b的差值的绝对值小于k。找到最大的b输出,如果找不到,那就输出-1

 

题解:

很简单嘛,找到上下限直接二分。下限就是所有物品中最小的价格。上限就是所有物品中最大价格加上k

 

代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<map>
 6 #include<math.h>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn=1e5+5;
10 const int mod=26;
11 const int INF=0x3f3f3f3f;
12 const int block=300;
13 int main()
14 {
15     int t;
16     scanf("%d",&t);
17     while(t--)
18     {
19         int b,n,k,minn=INF,maxx=0;
20         scanf("%d%d",&n,&k);
21         for(int i=1;i<=n;++i)
22         {
23             scanf("%d",&b);
24             minn=min(minn,b);
25             maxx=max(maxx,b);
26         }
27         int mid=(minn+maxx)/2;
28         if(mid-minn<=k && maxx-mid<=k)
29         {
30             int ans=mid,m,l=mid,r=maxx+k;
31             while(l<=r)
32             {
33                 m=(l+r)/2;
34                 if(m-minn<=k)
35                 {
36                     ans=m;
37                     l=m+1;
38                 }
39                 else r=m-1;
40             }
41             printf("%d\n",ans);
42         }
43         else printf("-1\n");
44     }
45     return 0;
46 }
View Code

 

c题题意:

最开始有k电量,你需要玩n个回合的游戏,每一回合你可以有两个选择

1、玩游戏,但是要消耗a电量

2、边充电边玩,消耗b电量

还有一个限制:如果电量小于等于a,那就不可以玩游戏;如果电量小于等于b那就不可以边充边玩

如果玩游戏玩不了n个回合,就输出-1,否则就输出你玩游戏的次数(可不是边充边玩)

 

题解:

思路很容易想,但是就是实现难!

你可以先n个回合都选择第二种模式来玩游戏,看电量够不够。如果不够就直接输出-1

这里判断就可以先玩n-1个回合,看看剩下的电量大不大于b。如果大于那就证明可以玩够n个回合,否则就不可以

因为电量必须大于b才能边充边玩

然后就二分 选择了几次第一个选择(即消耗电量为a) ,每一次的判断都类似上面的判断方式

 

还有就是要用long long

代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<map>
 6 #include<math.h>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn=1e5+5;
10 const int mod=26;
11 const int INF=0x3f3f3f3f;
12 const int block=300;
13 ll k,n,a,b;
14 bool check(ll x)
15 {
16     ll cha,ci;
17     if(x)
18     {
19         if(k-(a*(x-1))<=a) return 0;
20     }
21 
22     cha=k-a*x;
23     ci=n-x;
24     if(ci==0) return 1;
25     if(cha-(b*(ci-1))<=b) return 0;
26     else return 1;
27 }
28 int main()
29 {
30     ll t;
31     cin>>t;
32     while(t--)
33     {
34         cin>>k>>n>>a>>b;
35         if(k-(b*(n-1))<=b)
36         {
37             printf("-1\n");
38             continue;
39         }
40         else
41         {
42             ll l=0,r=n,m,ans=0;
43             while(l<=r)
44             {
45                 m=(l+r)>>1;
46                 if(check(m))
47                 {
48                     ans=m;
49                     l=m+1;
50                 }
51                 else r=m-1;
52             }
53             printf("%I64d\n",ans);
54         }
55     }
56     return 0;
57 }
View Code

 

D题题意:

给你n个糖果,每一个糖果有一个种类,你需要用这些不同种类的糖果来弄成一个礼物

但是这个礼物里面各 种类 糖果的数量不能相同,你需要找出来这个礼物最多能由多少糖果构成

 

题解:

你会发现,如果一种糖果的个数是n,那么它可以拿出n-1、n-2、n-3来放入礼物中

 

注释+代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<map>
 6 #include<math.h>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn=2e5+5;
10 const int mod=26;
11 const int INF=0x3f3f3f3f;
12 const int block=300;
13 int v[maxn],w[maxn];
14 int main()
15 {
16     int t;
17     scanf("%d",&t);
18     while(t--)
19     {
20         int n,a,maxx=0;
21         scanf("%d",&n);
22         for(int i=1;i<=n;++i) //这里不能用memset,要不然会超时
23             v[i]=w[i]=0;
24         for(int i=1;i<=n;++i)
25         {
26             scanf("%d",&a);
27             w[v[a]]--;  //w是记录有多少种糖果且这种糖果的数量是v[a]
28             v[a]++;    //v是记录每一种糖果的数量
29             w[v[a]]++;
30             //printf("%d %d %d\n",a,v[a],w[v[a]]);
31             maxx=max(maxx,v[a]);
32         }
33         int ans=0,sum=0;//printf("%d**\n",maxx);
34         for(int i=maxx;i>0;--i)
35         {
36 
37             ans+=w[i];
38             if(ans>0)  //如果你有一种糖果数量是5,此时这个可以来拿出来4个,来填充  
39  //礼物,也可以都拿出来,这要看有没有其他种类的糖果也有这个数量个糖果
40                 sum+=i,ans--;
41         }
42         printf("%d\n",sum);
43     }
44     return 0;
45 }
View Code

 

E题题意:

给你一个长为n的字符串,你需要从中找出来k个不重复的子序列(注意是子序列而不是子串。子序列不需要连续,可以再原字符串中间删除字母)。如果可以找到输出你删除的总字母个数(你要是这个值尽可能地小),如果不能输出-1

 

题解:

如果直接暴力dfs,那就相当于2^100,肯定会超时,那我们注意到k的值比较小,所有我们就可以找到k个子序列就可以了。又因为题目有要求输出的值尽量小。所以我们就可以按删除字符从小到大来枚举

我这里采用set去重

 

代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<map>
 6 #include<math.h>
 7 #include<set>
 8 #include<queue>
 9 using namespace std;
10 typedef long long ll;
11 const int maxn=2e5+5;
12 const int mod=26;
13 const int INF=0x3f3f3f3f;
14 const int block=300;
15 
16 int main()
17 {
18     int n,k,ans=0;
19     queue<string>r;
20     set<string>str;
21     string s;
22     cin>>n>>k;
23     cin>>s;
24     r.push(s);
25     str.insert(s);
26     while(!r.empty() && str.size()<k)
27     {
28         string ss=r.front();
29         r.pop();
30         int len=ss.size();
31         //printf("%d %d**\n",ss.length(),ss.size());
32         for(int i=0;i<len;++i)
33         {
34             string fresh=ss;
35             fresh.erase(i,1);
36             //cout<<fresh<<"**"<<endl;
37             if(!str.count(fresh) && str.size()<k)
38             {
39                 //cout<<1<<endl;
40                 r.push(fresh);
41                 str.insert(fresh);
42                 ans+=n-fresh.size();
43                 if(str.size()==k) break;
44             }
45         }
46     }
47     if(str.size()<k)
48         printf("-1\n");
49     else printf("%d\n",ans);
50 }

 

posted @ 2019-09-20 10:22  kongbursi  阅读(180)  评论(0编辑  收藏  举报