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; }
下面是[swust]MAXX的解释:
[swust]MAXX(405022026) 21:22:07
仔细想想就明白了:因为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; }
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; }