A题: 将夹杂在1中的0给删除即可。
#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=2e5+5;
int main()
{
string s;
int T;
scanf("%d",&T);
while(T--){
cin>>s;
int j=0,k=0,num=0;
int n=s.size();
for(int i=0;i<n;i++){
if(s[i]=='1'){j=i;break;}
}
for(int i=n-1;i>=0;i--){
if(s[i]=='1'){k=i;break;}
}
for(int i=j;i<k;i++){
if(s[i]=='0'){num++;}
}
printf("%d\n",num);
}
return 0;
}
B题: 答案具有单调性,直接二分枚举最少天数
#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=2e5+5;
bool check(ll mid,ll g,ll b,ll n)
{
n=(n+1)/2;
ll m=g+b;
if((mid/m*g+min(mid%m,g))>=n){return true;}
else{return false;}
}
int main()
{
int T;
ll n,g,b;
scanf("%d",&T);
while(T--){
scanf("%lld%lld%lld",&n,&g,&b);
ll l=n,r=1e18,ans;
while(l<=r){
ll mid=(l+r)>>1;
if(check(mid,g,b,n)){
ans=mid,r=mid-1;
}
else{
l=mid+1;
}
}
printf("%lld\n",ans);
}
return 0;
}
C题: dfs+建边。
1.相邻字符建立一条边,再判断一个字符是否最多相邻两个字符。
2.对 度数 < 2 && 未访问字符 进行dfs。(为啥对度 < 2 的进行搜索呢? 你想一下,情况1:孤立的一个字符;情况2:仅连接一个字符。我们假设答案YES的话,那么最终的排序必然是一条链,我们对孤立字符不考虑的话,那可以对链两端( 度1 )开始dfs出该链,若你对度2的考虑你的链将不正确,无法准确排出另一方向的链)
3.若存在为访问的点(度都为2构成环去了),直接输出NO
#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include <bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;
string p;
char s[205];
bool vis[30],ans[30][30];
int indx[30];
void dfs(int now)
{
if(vis[now]){return ;}
vis[now]=true;p+=now+'a';
for(int i=0;i<26;i++){
if(!vis[i]&&ans[now][i]){
dfs(i);
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
mem(ans,false);mem(vis,false);mem(indx,0);p="";
scanf("%s",s+1);
for(int i=2;s[i];i++){
int a=s[i-1]-'a';
int b=s[i]-'a';
ans[a][b]=ans[b][a]=true;
}
for(int i=0;i<26;i++){
ans[i][i]=false;
for(int j=0;j<26;j++){
if(ans[i][j]){indx[i]++;}
}
}
bool flag=false;
for(int i=0;i<26;i++){
if(indx[i]>2){printf("NO\n");flag=true;break;}
}
if(flag){continue;}
for(int i=0;i<26;i++){
if(!vis[i]&&indx[i]<2){dfs(i);}
}
for(int i=0;i<26;i++){
if(!vis[i]){printf("NO\n");flag=true;break;}
}
if(flag){continue;}
printf("YES\n");cout<<p<<endl;
}
return 0;
}
D题: 直接暴力处理即可。
1.可以直接判断无法构成的情况。
2.预先处理出二进制状态下每位的个数 bit[] ,再将n转化为二进制形式从低位开始处理,如果该位bit[]>0,说明可以用去组合;反之,向高位寻找第一个bit[]>0,然后用它去拆分直至拆分到当前位。
3.处理完当前位后,需进行合并到高位,bit [i+1] += bit [i] / 2;
#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include <bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;
int bit[66];
int main()
{
int T,m,ant,cnt;
ll sum,n;
scanf("%d",&T);
while(T--){
mem(bit,0);cnt=0;sum=0;
scanf("%lld%d",&n,&m);
for(int i=1,j;i<=m;i++){
scanf("%d",&j);sum+=j;
for(int k=0;k<30;k++){
if((1<<k)==j){bit[k]++;}
}
}
if(sum<n){printf("-1\n");continue;}
for(int i=0;i<60;i++){
if(n&(1ll<<i)){
for(int j=i;j<60;j++){
if(bit[j]){
bit[j]--;
for(int k=i;k<j;k++){
bit[k]++;
}
break;
}
cnt++;
}
}
bit[i+1]+=bit[i]/2;
}
printf("%d\n",cnt);
}
return 0;
}