1.Codeforces Round #659 (Div. 2) A
题意:给定一个数组包含n个元素,表示n+1个字符串相邻两个字符串中相同的前缀字符子串长度。求这n+1个字符串。
字符串符合条件即可,可能的情况很多很多,所以尽可能的用的字符种类少点就好。wa了一次,因为考虑少了,想着仅用一种字符实现字符串相邻的前缀子串相同。具体做法就是看某一个字符串和两边相邻相同字符数,包含的字符数要多于两个相邻的字符数。先复制前一个字符串的前几个字符,如果还需要更多的字符,那就换一种字符补齐该有的字符数,而后面的字符串执行相同操作实现某字符串两侧符合应该相等的字符数。
#include<iostream>
#include<iomanip>
#include<fstream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdio>
#include<map>
#include<queue>
#include<vector>
#include<utility>
#include<ostream>
#include<istream>
typedef long long ll;
using namespace std;
#define mod 1e9+7
#define PI acos(-1.0)
const ll maxn=2*1e5;
const int mx=(1<<20)+99;
ll n,m,k,ans,aans,flag,num,cnt,l,r,a[200];
char c,s[200];
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int t;
cin>>t;
for(int o=1;o<=t;++o)
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
c='a';
for(int i=1;i<=n+1;i++)
{
l=r=0;
if(i==1)
{
for(int j=1;j<=a[i];j++)
{
cout<<c;
s[j]=c;
}
aans=a[i];
cout<<(i%2?"y":"z");
cout<<endl;
}
else if(i==n+1)
{
for(int j=1;j<=a[n];j++)
cout<<s[j];
cout<<(i%2?"y":"z");
cout<<endl;
}
else
{
aans=max(a[i],a[i-1]);
if(aans>a[i-1])
{
if(c=='x') c='a';
else c++;
}
for(int j=1;j<=aans;j++)
{
if(j<=a[i-1])
cout<<s[j];
else
{
cout<<c;
s[j]=c;
}
}
cout<<(i%2?"y":"z");
cout<<endl;
}
}
}
return 0;
}
2.Codeforces Round #659 (Div. 2) B1
题意:海岸离岛屿n米,想从海岸游到对岸去。中间每个地方(每一米的地方)都有个初始深度,海浪会随时间改变海水深度(从0递增到l后再递减到0,如此往复),可以选择某时刻向前游一米或者不动了,问能不能到达对岸。
想着应该可以用接近暴力的方法做出来,但两次理解错题意,然后就放弃了。所以先水上别人dp的代码,再换个时间看下吧,我觉得应该贪心可以的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e4 + 7;
int T,n,k,l,h;
int dp[107][maxn],a[maxn];
int main(){
scanf("%d",&T);
while(T--){
memset(dp,-1,sizeof(dp));
scanf("%d%d%d",&n,&k,&l);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<=2 * k * n;i++) dp[0][i]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=2 * k * n;j++){
if(dp[i-1][j-1]==-1&&dp[i][j-1]==-1) continue;
if( j % (2 * k) < k) h = a[i] + j % k;
else h = a[i] + k -(j % k);
if(h<=l) dp[i][j]=0;
}
}
int fl=0;
for(int i=0;i<=10000;i++){
if(dp[n][i]==0) fl=1;
}
if(fl==1) printf ("YES\n");
else printf ("NO\n");
}
}
3.Codeforces Round #659 (Div. 2) C
题意:给定两个字符串,每次可以将a串中一定量的相同字母换成另一个“大”的字母,问能不能使a等于b,若能求最少步数。
原本想法是记录每种字母的所有可能做出的变化,再减去某些特殊的较大的变化,这些特殊的较大的变化能够跟随着较小的变化一步一步实现而不需要单独变化一次。但搞了一晚上差不多三个小时还是没搞出来。所以,放弃了自己的想法,看了一下别人的题解,发现其实可以把我的想法抽象出来,只考虑不同字母的变化而不去考虑原先两个字符串了,这样就可以简单很多。其实我的代码过不了就是因为还是依托的原先的两个字符串,摆脱它的话其实和别人的思路和代码基本一致。
#include<iostream>
#include<iomanip>
#include<fstream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdio>
#include<map>
#include<queue>
#include<vector>
#include<utility>
#include<ostream>
#include<istream>
typedef long long ll;
using namespace std;
#define mod 1e9+7
#define PI acos(-1.0)
const ll maxn=1*1e5;
const int mx=(1<<20)+99;
ll n,m,ans,aans,flag,fid,num,cnt[30][30];
char a[maxn+10],b[maxn+10];
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int t;
cin>>t;
for(int o=1;o<=t;++o)
{
cin>>n>>a>>b;
bool flag=1;
memset(cnt,0,sizeof(cnt));
for(int i=0;i<n;i++)
{
if(a[i]!=b[i])
{
if(a[i]<b[i])
cnt[a[i]-'a'][b[i]-'a']++;
else flag=0;
}
}
if(flag)
{
ll cur; ans=0;
for(int i=0;i<20;i++)
{
flag=0;
for(int j=i+1;j<20;j++)
{
if(cnt[i][j])
{
cur=j;
flag=1;
break;
}
}
if(flag)
{
ans++;
for(int j=i+1;j<20;j++)
{
if(cnt[i][j])
cnt[cur][j]=1;
}
}
}
cout<<ans<<endl;
}
else cout<<-1<<endl;
}
return 0;
}
总结:花了上午的一个多小时加一晚上也没搞出多少题来,老师说以前的晚上打的比赛很多人没整理,我不知道别人是怎样的,反正我是因为搞不出来。我其实想整理一下的,但能够做出来的题很少,也不好意思发了。不过,既然花时间琢磨思考了,也想着去整理了,那么或多或少的搞出来吧,了胜于无啊也是。