开个新号,这次做出了三道题,上分!!
A. Erasing Zeroes
题意:给你一个由
解析:大水题,找到最左边的
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#define INF 1e9
using namespace std;
const int maxn=110;
int t,n;
char s[110];
int main()
{
scanf("%d",&t);
while(t--)
{
int l=0,r=0,ans=0;
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;i++)
if(s[i]=='1')
{
l=i;
break;
}
for(int i=len;i>=1;i--)
if(s[i]=='1')
{
r=i;
break;
}
for(int i=l;i<=r;i++)
if(s[i]=='0')
ans++;
printf("%d\n",ans);
}
return 0;
}
B. National Project
题意:你要修一条长度为
解析:简单模拟,分类讨论情况即可。首先如果
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#define INF 1e9
using namespace std;
const int maxn=1e4;
long long t,n,g,b;
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld",&n,&g,&b);
long long num=(n+1)/2;
long long p=num/g;
if(num<=g)
{
printf("%lld\n",n);
continue;
}
long long ans=0;
if(num%g)
{
ans=1ll*p*(g+b);
ans+=num%g;
}
else
ans=1ll*p*(g+b)-b;
printf("%lld\n",max(ans,n));
}
return 0;
}
C. Perfect Keyboard
题意:
解析:一道较简单的构造题。用
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#define INF 1e9
using namespace std;
const int maxn=210;
int t,len,p[31][2];
char s[maxn];
bool vis[31];
int main()
{
scanf("%d",&t);
while(t--)
{
bool flag=1;
memset(p,0,sizeof(p));
memset(vis,0,sizeof(vis));
scanf("%s",s+1);
len=strlen(s+1);
for(int i=1;i<len;i++)
{
int q=s[i]-'a'+1;
vis[q]=1;
int r=s[i+1]-'a'+1;
if(vis[r])
{
if(r==p[q][0]||r==p[q][1])
continue;
else
{
flag=0;
break;
}
}
else
{
if(!p[q][0])
{
p[q][0]=r;
p[r][1]=q;
}
else if(!p[q][1])
{
p[q][1]=r;
p[r][0]=q;
}
else
{
flag=0;
break;
}
}
}
vis[s[len]-'a'+1]=1;
if(!flag)
printf("NO\n");
else
{
printf("YES\n");
int f=s[1]-'a'+1;
while(p[f][0])
f=p[f][0];
while(f)
{
printf("%c",f+'a'-1);
f=p[f][1];
}
for(int i=1;i<=26;i++)
if(!vis[i])
printf("%c",i+'a'-1);
printf("\n");
}
}
return 0;
}
D. Fill The Bag
题意:你有一个容量为
解析:一道很好的贪心和二进制题。我们首先用一个数组
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#define INF 1e9
using namespace std;
const int maxn = 101010;
long long cnt[70],n,ans;
int t,m,a[maxn];
int main()
{
scanf("%d",&t);
while(t--)
{
ans=0;
scanf("%lld%d",&n,&m);
for(int i=0;i<64;i++)
cnt[i]=0;
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
for(int j=0;j<=30;j++)
if(a[i]==(1<<j))
cnt[j]++;//分解每一位,用数组存储指数
}
bool flag=true;
for(int i=0;i<64;i++)
{
if(n&(1ll<<i))//如果n第i位上为1
{
if(cnt[i])
cnt[i]--;//有盒子直接减
else
{
int p=0;
for(int j=i+1;j<64;j++)//找比它大的盒子
if(cnt[j])
{
p=j;
break;
}
if(!p)
flag=false;//找不到标记退出
else
{
cnt[p]--;//大盒子用1个
for(int j=p-1;j>=i;j--)
{
cnt[j]++;
ans++; //分解盒子
}
}
}
}
if(!flag)
break;
if(cnt[i]>=2)
{
cnt[i+1]+=cnt[i]/2;//因为用2个2^i盒子和1个2^(i+1)盒子等效,而第i位已经遍历过了,所以把剩下的盒子全换成大盒子
cnt[i]/=2;
}
}
if(flag)
printf("%lld\n",ans);
else
printf("-1\n");
}
}
E. Erase Subsequences
题意:给你两个字符串
解析:
首先我们来看下题目中的一些概念(之前我一直天真的以为子串和子序列是一个东西)
子串
子串是指字符串中任意连续的一段字符构成的字符串。
子序列
子序列是指字符串中任意删去一些字符后,剩下的字符按顺序构成的字符串。
两者的区别就在于子串要求连续,而子序列不要求。
接下来来分析一下:这是一道很好的匹配型
在
然后就是让
然后令
接下来就是如何解决在
序列自动机
序列自动机能经过
定义
for(int i=1;i<=26;i++)
nex[n][i]=n+1;//第n个位置后无任何字符,设置为不合法
for(int i=n;i>=1;i--)
{
for(int j=1;j<=26;j++)
nex[i-1][j]=nex[i][j];
nex[i-1][s[i]-'a'+1]=i;
}
然后顺便给出即可序列自动机解决问题的代码板子:
求子序列个数:
int dfs(int x)//代表字符串第x位
{
if(f[x])
return f[x];//记忆化
for(int i=1;i<=26;i++)
if(nex[x][i]<=n)
f[x]+=dfs(nex[x][i]);//如果第x位后有字符i,加上这部分的贡献
return ++f[x];//第x位结束的子序列依然是子序列,最后加上这一个
}
求两个串的公共子序列个数,即对
int dfs(int x,int y)//串1的第x位,串2的第y位
{
if(f[x][y])
return f[x][y];//记忆化
for(int i=1;i<=26;i++)
if(nex1[x][i]<=n&&nex2[y][i]<=m)
f[x][y]+=dfs(nex1[x][i],nex2[y][i]);
return ++f[x][y];
}//思路大同小异
求一个串的回文子序列个数,即对原串和反串分别构造
int dfs(int x,int y)
{
if(f[x][y])
return f[x][y];
for(int i=1;i<=26;i++)
if(nex1[x][i]<=n&&nex2[y][i]<=n)
{
if(nex1[x][i]+nex2[y][i]>n+1)
continue;
if(nex1[x][i]+nex2[y][i]<n+1)//偶串
f[x][y]++;
f[x][y]+=dfs(nex1[x][i],nex2[y][i]);
}
return ++f[x][y];
}
然后就很好做了,状态转移方程变为:
最后只需判断
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#define INF 1e9
using namespace std;
const int maxn=410;
int T,len1,len2;
int nex[maxn][31];
int dp[maxn][maxn];
char s[maxn],t[maxn];
void ready(int n)//构造序列自动机
{
for(int i=1;i<=26;i++)
nex[n][i]=n+1;//第n个位置后无任何字符,设置为不合法
for(int i=n;i>=1;i--)
{
for(int j=1;j<=26;j++)
nex[i-1][j]=nex[i][j];
nex[i-1][s[i]-'a'+1]=i;
}
}
bool check(int n)//n代表a串长
{
int m=len2-n;//m代表b串长
dp[0][0]=0;
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
{
if(!i&&!j)
continue;
dp[i][j]=len1+1;
if(i&&dp[i-1][j]<len1)
dp[i][j]=min(dp[i][j],nex[dp[i-1][j]][t[i]-'a'+1]);
if(j&&dp[i][j-1]<len1)
dp[i][j]=min(dp[i][j],nex[dp[i][j-1]][t[n+j]-'a'+1]);
}
return dp[n][m]<=len1;
}
void solve()
{
scanf("%s%s",s+1,t+1);
len1=strlen(s+1);
len2=strlen(t+1);
ready(len1);
for(int i=1;i<=len2;i++)
if(check(i))
{
printf("YES\n");
return ;
}
printf("NO\n");
return ;
}
int main()
{
scanf("%d",&T);
while(T--)
solve();
return 0;
}