这次rank23~又回到紫名啦~
A.枚举插入的位置和插入的字符,暴力判断即可。
#include <iostream> #include <cmath> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> using namespace std; string S; int s[20],n[20]; int main() { cin>>S; for (int i=0;i<S.length();i++) s[i+1]=(int)(S[i]-'a'+1); for (int i=1;i<=S.length()+1;i++) for (int k=1;k<=26;k++) { n[i]=k; for (int j=1;j<=i-1;j++) n[j]=s[j]; for (int j=i;j<=S.length();j++) n[j+1]=s[j]; int l=1,r=S.length()+1; bool f=false; while (n[r]==n[l]) { r--,l++; if (l>=r) { f=true; break; } } if (f) { for (int j=1;j<=S.length()+1;j++) cout<<(char)('a'+n[j]-1); cout<<endl; return 0; } } cout<<"NA"<<endl; return 0; }
B.暴力dfs每一种颜色
#include <iostream> #include <cmath> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> using namespace std; int tot=0,n,m,h[105],q,de,c[105],v[105]; struct edge { int c,y,ne; }e[10000]; void Add(int x,int y,int c) { tot++; e[tot].y=y; e[tot].c=c; e[tot].ne=h[x]; h[x]=tot; } void dfs(int x,int now) { if (x==de) { c[now]=1; return; } for (int i=h[x];i;i=e[i].ne) { if (e[i].c!=now) continue; int y=e[i].y; if (!v[y]) { v[y]=1; dfs(y,now); v[y]=0; } } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y,co; scanf("%d%d%d",&x,&y,&co); Add(x,y,co);Add(y,x,co); } scanf("%d",&q); while (q--) { int x; scanf("%d%d",&x,&de); memset(v,0,sizeof(v)); memset(c,0,sizeof(c)); v[x]=1; for (int i=h[x];i;i=e[i].ne) { int y=e[i].y; v[y]=1; dfs(y,e[i].c); v[y]=0; } int ans=0; for (int i=1;i<=m;i++) ans+=c[i]; cout<<ans<<endl; } return 0; }
C.
这道题显然是个dp,但是暴力的dp超时超空间。
仔细观察可以发现最多只有500种步行的长度,比如d=1,假设每次都增加1,不到250就超过30000了;每次减少一步也同理。
这个时候dp就是500*30000了,可以过的。
注意这道题中说超过30000就不能走!!
#include <iostream> #include <cmath> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #define M 30005 #include <queue> using namespace std; struct data { int p,n; }; int c[M],n,d,f[M][505],b[M],k[M]; int main() { int ma=0; scanf("%d%d",&n,&d); for (int i=1;i<=n;i++) { int x; scanf("%d",&x); c[x]++; ma=max(ma,x); } if (d<=250) { for (int i=1;i<=d+250;i++) b[i]=i,k[i]=i; } else { int now=0; for (int i=d-250;i<=min(30000,d+250);i++) b[++now]=i,k[i]=now; } memset(f,-1,sizeof(f)); f[d][k[d]]=c[d]; int ans=f[d][k[d]]; for (int i=d;i<=min(ma,30000-1);i++) for (int j=1;j<=500;j++) { if (f[i][j]==-1) continue; int m=b[j]; for (int now=max(m-1,1);now<=m+1;now++) { int de=i+now; if (de>30000) continue; f[de][k[now]]=max(f[de][k[now]],f[i][j]+c[de]), ans=max(ans,f[de][k[now]]); } } cout<<ans<<endl; return 0; }
考试A了前三个。。
D题看题解明白了:
找每一个连通的块,设块中有x个点。
如果其中没有环,那么这个块要建x-1条边就可以保证全部满足,因为没有环的话,就一定可以拓扑排序,那么把拓扑排序之后的点连成一条链,就可以满足要求。
如果有环的话就要x条边了。
#include <iostream> #include <cmath> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <queue> using namespace std; int v[200005],h2[200005],in[200005],h[200005],tot=0,k,n,m; struct edge { int y,ne; }e[400005]; queue<int> q; void Add(int x,int y) { tot++; e[tot].y=y; e[tot].ne=h[x]; h[x]=tot; } void Add2(int x,int y) { tot++; e[tot].y=y; e[tot].ne=h2[x]; h2[x]=tot; } void dfs(int x) { if (!in[x]) q.push(x); tot++; v[x]=1; for (int i=h2[x];i;i=e[i].ne) { int y=e[i].y; if (v[y]) continue; dfs(y); } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); Add(x,y); Add2(x,y);Add2(y,x); in[y]++; } int ans=0; for (int i=1;i<=n;i++) if (!v[i]) { tot=0; k=0; while (!q.empty()) q.pop(); dfs(i); if (tot==1) continue; int ok=0; while (!q.empty()) { int x=q.front(); q.pop(); ok++; if (ok>tot) break; for (int i=h[x];i;i=e[i].ne) { in[e[i].y]--; if (!in[e[i].y]) q.push(e[i].y); } } if (ok==tot) ans+=(tot-1); else ans+=tot; } cout<<ans<<endl; return 0; }
时间: 2024-11-12 22:13:00