你最愿意做的哪件事,才是你的天赋所在

0%

Codeforces Round #608 (Div. 2)

题目链接

A

思路

贪心,因为只有一个共享的,所以钱多的先使用

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long a,b,c,d,e,f;
cin>>a>>b>>c>>d>>e>>f;
long long ans = 0;
if(e>f){
ans+=min(a,d)*e;
d-=min(a,d);
ans+=min(d,min(b,c))*f;
}
else
{
ans+=min(d,min(b,c))*f;
d-=min(d,min(b,c));
ans+=min(a,d)*e;
}
cout<<ans<<endl;
}

B

思路

观察到每次都可以让两个相同的变换,但是如果是奇数的话就不可能,所以判断白色块和黑色块的奇偶性,然后偶数块数的就可以变为相反的,每次选取两端的,然后利用前缀和数组来维护,最后我们去除无用的操作即可。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[800];
int pre[800];
int ji,ou;
vector<int>j;
vector<int>o;
vector<int>v;
int main()
{
int n;
scanf("%d",&n);
string s;
int ans = 0;
cin>>s;
for(int i=0;i<n;i++)
{
if(s[i]=='B')o.push_back(i+1),ou++;
else j.push_back(i+1),ji++;
}
if(ji%2==1&&ou%2==1)return 0*printf("-1\n");
else
{
if(ji%2==0)
{
for(int i=0;i<j.size()/2;i++)
{
pre[j[i]]=1;
pre[j[i+j.size()/2]]=-1;
}
}
else
{
for(int i=0;i<o.size()/2;i++)
{
pre[o[i]]=1;
pre[o[i+o.size()/2]]=-1;
}
}
}
for(int i=1;i<=n;i++)pre[i]+=pre[i-1];
for(int i=1;i<=n;i++)
{
pre[i]%=2;
ans+=(pre[i]==1);
}
printf("%d\n",ans);
for(int i=1;i<=n;i++)if(pre[i]==1)printf("%d ",i);
}

C

思路

很简单的一道题,建立的tent在学校的四周的最靠近点上的时候都可以,只有四种情况,然后考虑不同的情况即可

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int up,leftt,rightt,down;
int main()
{
int n,sx,sy;
cin>>n>>sx>>sy;
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d %d",&x,&y);
if(x<sx)leftt++;
else if(x>sx)rightt++;
if(y<sy)down++;
else if(y>sy)up++;
}
if(up>=down&&up>=leftt&&up>=rightt)printf("%d\n%d %d",up,sx,sy+1);
else if(down>=up&&down>=leftt&&down>=rightt)printf("%d\n%d %d",down,sx,sy-1);
else if(leftt>=up&&leftt>=rightt&&leftt>=down)printf("%d\n%d %d",leftt ,sx-1,sy);
else printf("%d\n%d %d",rightt,sx+1,sy);
}

D

留坑

E

来填坑了,

思路

分奇数偶数,假设x为奇数,那么能到达它的数有2x,2x+1,2x+2,2x+3,然后在推一次4x,4x+1,…,4x+7,偶数的话就先+1到奇数然后这样就可以了。
这样我们就能在$log_2n$复杂度之内求出一个数的Path了,然后再考虑求最大的答案,首先证明单调性,分奇数偶数,小的奇数肯定比大的奇数的path值要大因为我们再上面证明了小的奇数可以由大的奇数推出来,因此我们就可以使用二分的方式求出答案。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll k,n;
ll calji(ll x)
{
ll ans = 0;
ll res = 1;
while(x<=k)
{
ans+=res;
x=2*x+1;
res*=2;
}
x-=res-1;
if(k>=x)
ans+=(k-x+1);
return ans;
}
ll calou(ll x)
{
if(x==k)return 1;
if(x==k+1)return 2;
ll ans = 0;
ll res = 2;
x=x+1;
while(x<=k)
{
ans+=res;
x*=2;
x+=1;
res*=2;
}
x-=res-1;
if(k>=x)ans+=(k-x+1);
return ans;
}
int main()
{
scanf("%lld %lld",&k,&n);
ll l = 1,r=k;
ll jians = l;
while(l<r)//二分奇数
{
ll mid = (l+r)>>1;
if(mid%2==0)mid++;
ll num = calji(mid);
if(num>=n)
{
l=mid+1;
jians = mid;
}
else r=mid-1;
}

ll left=1,right=k,ouans=left;
while(left<right)//
{
ll mid = (left+right)>>1;
if(mid%2==1)mid++;
ll num = calou(mid);
if(num >=n ){
left = mid +1;
ouans=mid;
}
else right = mid - 1;
}
printf("%lld\n",max(jians,ouans));
}
-------------你最愿意做的哪件事才是你的天赋所在-------------