A题:用短串去长串里里面找自己(找的时候把字符转换一起考虑),找到就是happy;
代码:
#include<stdio.h>
#include<string.h>
int mat[30][30];
char s[1100],str[1200],a[3],b[3];
int main()
{
int cas,m,i,cass;
scanf("%d",&cass);
for(cas=1;cas<=cass;cas++)
{
memset(mat,0,sizeof(mat));
scanf("%s%s",s,str);
scanf("%d",&m);
for(i=0;i<26;i++) mat[i][i]=1;
for(i=1;i<=m;i++){
scanf("%s%s",a,b);
mat[a[0]-'a'][b[0]-'a']=1;
}
for(i=m=0;str[i];i++)
{
if(!s[m]) break;
if(mat[str[i]-'a'][s[m]-'a']) m++;
}
printf("Case #%d: ",cas);
puts(!s[m]?"happy":"unhappy");
}
return 0;
}
B题:比赛的时候,没做出来,赛后在acdream群 看到[swust]MAXX大侠的解释,orz,突然醒悟,自己还是水平不够;
下面是[swust]MAXX的解释:
[swust]MAXX(405022026) 21:22:07
B题,关键是最后的答案比较小。
比方,n>=100,光是两两配合就有10000多个了,所以答案一定是小于等于2000。
就算n比较小,答案也是15000内的
[swust]MAXX(405022026) 21:24:14
所以用dp[i]表示和值为i的组合的个数,那么就能做了
比方,n>=100,光是两两配合就有10000多个了,所以答案一定是小于等于2000。
就算n比较小,答案也是15000内的
[swust]MAXX(405022026) 21:24:14
所以用dp[i]表示和值为i的组合的个数,那么就能做了
仔细想想就明白了:因为n个数最多能组合出2^n-1( C(n,0)去掉 )种,且2^14-1>10000所以最大值不会超过14个数相加的最大和也就是14000,至于当n>=100时最大值不会超过2000上面已经解释的很清楚了。
实现代码如下:
#include<stdio.h>
#include<string.h>
int dp[14100];
int Min(int a,int b){ return a<b?a:b;}
int main()
{
int cass,cas,i,j,n,m,L,k;
scanf("%d",&cass);
for(cas=1;cas<=cass;cas++)
{
scanf("%d%d",&n,&m);
if(n>100) L=2000;
else L=13000;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
scanf("%d",&k);
for(j=L;j>=0;j--)
{
dp[j+k]+=dp[j];
if(dp[j+k]>m)dp[j+k]=m+1;
}
dp[k]++;
}
for(i=0;i<=L;i++){
m-=dp[i];
if(m<=0) break;
}
printf("Case #%d: %d\n",cas,i);
}
return 0;
}
C题:lca经典问题了,用rmq,tarjan算法都可以解,前者用预处理,后者可以用离线+并查集(这种方法可能麻烦点,好久没写了);
rmq版的代码:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<map>
#include<string>
#include<set>
#include<algorithm>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
struct E
{
int t,next;
}edge[210000];
int ant,head[110000];
void add(int a,int b)
{
edge[ant].t=b;
edge[ant].next=head[a];
head[a]=ant++;
}
map <string,int > id;
char A[100],B[100];
int p[210000],pid[110000],k,dp[210000][25];
void dfs(int root,int dep)
{
int i;
pid[root]=++k;
p[k]=dep;
for(i=head[root];i!=-1;i=edge[i].next)
{
dfs(edge[i].t,dep+1);
p[++k]=dep;
}
}
int Min(int a,int b){ return a<b?a:b;}
int lca(int l,int r)
{
int i=0;
if(l==r) return p[l];
if(l>r) swap(l,r);
while((1<<i)<(r-l+1)) i++;
return Min(dp[l][i-1],dp[r-(1<<(i-1))+1][i-1]);
}
int vis[110000];
int main()
{
int cas,m,i,j,n,cnt,l,r,root,t;
scanf("%d",&cas);
while(cas--)
{
ant=cnt=0;
id.clear();
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(i=1;i<n;i++){
scanf("%s%s",A,B);
if(!id[A]) id[A]=++cnt;
if(!id[B]) id[B]=++cnt;
add(id[B],id[A]);
vis[id[A]]++;
}
for(i=1;i<=n;i++)
if(!vis[i]) root=i;
k=0;dfs(root,0);
for(i=1;i<=k;i++) dp[i][0]=p[i];
for(i=1;i<=20;i++)
for(j=1;(j+(1<<i)-1)<=k;j++)
dp[j][i]=Min(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);
while(m--){
scanf("%s%s",A,B);
l=pid[id[A]];r=pid[id[B]];t=lca(l,r);
printf("%d\n",p[l]-t+(t!=p[r]));
}
}
return 0;
}