场次链接
A、Erasing Zeroes
题目链接
题意 给你一个01字符串,你要删去0使得所有的1都连在一起,问最少要删几个0。
数据范围
1
≤
t
≤
100
1\leq t\leq 100
1≤t≤100,
1
≤
∣
s
∣
≤
100
1\leq |s|\leq 100
1≤∣s∣≤100
解 签到,计算两端有多少个0,再算一下有多少1,用长度减去即可。
复杂度
O
(
n
)
O(n)
O(n)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[105];
void work()
{
scanf("%s",a);
int l=strlen(a);
int sum=0;
int sum1=0;
int sum2=-1;
for(int i=0;i<l;i++){
if(a[i]=='1'){
sum++;
}
}
for(int i=0;i<l;i++){
if(a[i]=='1'){
sum1=i;
break;
}
}
for(int i=l-1;i>=0;i--){
if(a[i]=='1'){
sum2=i;
break;
}
}
printf("%d\n",max(0,sum2-sum1+1-sum));
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T=1;
scanf("%d",&T);
//cin>>T;
while(T--){
work();
}
}
B、National Project
题目链接
题意 你需要给n个物品涂上颜色,每秒可以涂1个,也可以选择不涂,前g秒可以涂白色,然后b秒可以涂黑,再是g秒涂白,……。要求白色的数量至少为n的一半(向上取整),问最少需要多少时间。
数据范围
1
≤
T
≤
1
0
4
1\leq T\leq 10^4
1≤T≤104,
1
≤
n
,
g
,
b
≤
1
0
9
1\leq n,g,b \leq 10^9
1≤n,g,b≤109
解 如果g>=b,那么直接n秒即可,再判断直接涂n秒是否可以满足白色超过一半。如果这俩都不行,那么白色必定涂一半,判断白色涂一半要多久即可
复杂度
O
(
1
)
O(1)
O(1)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void work()
{
ll n,g,b;
scanf("%lld%lld%lld",&n,&g,&b);
if(g>=b){
printf("%lld\n",n);
}else{
ll cnt=n/(g+b);
ll cnt1=n%(g+b);
ll tmp1=cnt*g+min(cnt1,g);
ll tmp2=cnt*b+max(0ll,cnt1-g);
if(tmp1>=tmp2){
printf("%lld\n",n);
}else{
n=(n+1)/2;
if(n%g!=0){
cnt=n/g*(g+b);
cnt+=n%g;
}else{
cnt=n/g*(g+b)-b;
}
printf("%lld\n",cnt);
}
}
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T=1;
scanf("%d",&T);
//cin>>T;
while(T--){
work();
}
}
C、Perfect Keyboard
题目链接
给你一个字符串,你要生成一个26字母的字符串,使得在给定串中相邻的字符在你生成的串中也相邻。
数据范围
1
≤
t
≤
1000
1\leq t\leq 1000
1≤t≤1000,
1
≤
∣
s
∣
≤
200
1\leq |s|\leq 200
1≤∣s∣≤200
解:将相邻字符连边存到set中(vector也行,set不重复方便一点),易得如果1个字符连了3个边,那么必定不可能。然后再是如果形成了一个环,那么也是不行的。可以想到,如果要满足题意并且存在,那么形成的图形应该是一条链,那么找到只连了一条边的点,然后跑一个dfs直接输出,再把没有出现过的字母输出即可。需要特判一下只有一个字符的情况。
复杂度
O
(
L
l
o
g
(
L
)
)
O(Llog(L))
O(Llog(L))
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[205];
set<int>s[26];
int vis1[26];
int vis2[26];
bool f=true;
void dfs(int past,int now)
{
vis1[now]=1;
for(auto v:s[now]){
if(v==past)continue;
if(vis1[v]){
f=false;
return;
}else{
dfs(now,v);
}
}
}
void dfs1(int past,int now)
{
vis2[now]=1;
printf("%c",now+'a');
for(auto v:s[now]){
if(v==past)continue;
dfs1(now,v);
}
}
void work()
{
f=true;
for(int i=0;i<=25;i++){
s[i].clear();
vis1[i]=0;
vis2[i]=0;
}
scanf("%s",a);
int l=strlen(a);
if(l==1){
printf("YES\n");
for(int i=0;i<=25;i++){
printf("%c",i+'a');
}
printf("\n");
return;
}
for(int i=0;i<l;i++){
if(i>0)s[a[i]-'a'].insert(a[i-1]-'a');
if(i<l-1)s[a[i]-'a'].insert(a[i+1]-'a');
}
for(int i=0;i<=25;i++){
if(s[i].size()>2){
printf("NO\n");
return;
}
}
for(int i=0;i<=25;i++){
if(s[i].size()){
dfs(-1,i);break;
}
}
if(!f){
printf("NO\n");return;
}
int cnt=0;
for(int i=0;i<=25;i++){
if(s[i].size()==2){
cnt++;
}
}
printf("YES\n");
for(int i=0;i<=25;i++){
if(s[i].size()==1){
dfs1(-1,i);
break;
}
}
for(int i=0;i<=25;i++){
if(!vis2[i]){
printf("%c",i+'a');
}
}
printf("\n");
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T=1;
scanf("%d",&T);
//cin>>T;
while(T--){
work();
}
}
D、Fill The Bag
题目链接
给你一个n和m个2的幂次数字,你可以进行操作将一个数字拆分成相等的2个,问要组合成n,最少要拆几次。
数据范围
1
≤
t
≤
1000
1\leq t\leq 1000
1≤t≤1000,
1
≤
n
≤
1
0
18
1\leq n\leq 10^{18}
1≤n≤1018,
1
≤
m
≤
1
0
5
1\leq m\leq 10^5
1≤m≤105,
1
≤
a
i
≤
1
0
9
1\leq a_i\leq 10^9
1≤ai≤109
解 将n拆分成二进制,从低往高找,同时将低的
a
a
a合并成高的,如果这位n有,并且m个数中也有,那么直接放上去,如果这位n有,m个数中无,那么继续往上找,找到第一个m个数中有的,进行拆分,拆分完后直接就从该位开始判断,因为下面的在拆分完后必定有。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[100005];
int b[63];
int vis[63];
void work()
{
ll n,m;
scanf("%lld%lld",&n,&m);
for(ll i=0;i<=62;i++){
if((n>>i)&1){
vis[i]=1;
}else{
vis[i]=0;
}
b[i]=0;
}
ll sum=0;
for(int i=1;i<=m;i++){
scanf("%lld",&a[i]);
sum+=a[i];
int cnt=0;
while(a[i]%2==0){
a[i]/=2;
cnt++;
}
b[cnt]++;
}
if(sum<n){
printf("-1\n");
return;
}
int ans=0;
for(int i=0;i<=62;i++){
b[i]+=b[i-1]/2;
if(vis[i]){
if(b[i]==0){
for(int j=i+1;j<=62;j++){
if(b[j]){
b[j]--;
ans+=j-i;
i=j-1;
break;
}
}
}else{
b[i]--;
}
}
}
printf("%d\n",ans);
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T=1;
scanf("%d",&T);
//cin>>T;
while(T--){
work();
}
}