渣诚解题报告在此,果然每次解题报告写得都比我认真多了Orz……那我就扔个标程随便写写好了……
A. 新·神魔之井
陈题,角谷猜想。不多说。
#include<cstdio>
using namespace std;
int main()
{
int n,ans;
while(~scanf("%d",&n))
{
for(ans=0; n>1; ++ans)
n=(n&1)?n*3+1:n/2;
printf("%d\n",ans);
}
}
B. AString.h(III)
其实就是HDU1274变了个题目描述,这道题没办法随机数据,数据编得直恶心……递归随便搞搞即可。非递归不好写但我也写了一份。
#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
char str[105];
int len;
int translate(int pos)
{
for(; pos<len&&str[pos]!=')'; ++pos)
{
int num=0,tmp=-1;
for(; isdigit(str[pos]); ++pos)
num=num*10+str[pos]-'0';
if(num==0)
++num;
while(num--)
if(str[pos]=='(')
tmp=translate(pos+1);
else
printf("%c",str[pos]);
if(tmp!=-1)
pos=tmp;
}
return pos;
}
int main()
{
while(~scanf("%s",str))
{
len=strlen(str);
translate(0);
putchar('\n');
}
}
#include<iostream>
#include<string>
#include<cctype>
#include<stack>
using namespace std;
stack<pair<string,int> > s;
int main()
{
string str;
while(cin>>str)
{
string ans="";
for(int i=0; i<str.size(); ++i)
{
if(str[i]==')')
{
pair<string,int> top=s.top();
s.pop();
string tmp=ans;
while(--top.second)
ans+=tmp;
ans=top.first+ans;
continue;
}
int num=0;
for(; isdigit(str[i]); ++i)
num=num*10+str[i]-'0';
if(num==0)
++num;
if(str[i]=='(')
{
s.push(make_pair(ans,num));
ans="";
continue;
}
while(num--)
ans+=str[i];
}
while(!s.empty())
{
pair<string,int> top=s.top();
s.pop();
string tmp=ans;
while(--top.second)
ans+=tmp;
ans=top.first+ans;
}
cout<<ans<<endl;
}
}
C. AString.h(IV)
是出了两年的上机原题原数据,每次都只改了题目描述罢了……通配符是唬人的,以通配符为分割,一段段分别KMP就好。
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=10005;
char str[MAXN],s[MAXN];
int next[MAXN],sl,tl;
void getnext(int p,int l)
{
int j=0,k=-1;
next[0]=-1;
while(p+j<l)
{
while(k>-1&&s[p+j]!=s[p+k])
k=next[k];
++j;
++k;
next[j]=(s[p+j]==s[p+k])?next[k]:k;
}
}
int kmp(int pos,int p,int l)
{
int i=0,j=0;
getnext(p,l);
while(pos+i<sl)
{
while(j>-1&&str[pos+i]!=s[p+j])
j=next[j];
++i;
if(++j==l)
return i;
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
getchar();
gets(str);
sl=strlen(str);
tl=strlen(s);
bool flag=true;
int pos=0,p=0;
while(flag&&p<tl)
{
int q=p;
while(q<tl&&s[q]!='*')
++q;
pos=kmp(pos,p,q-p);
p=q+1;
if(pos==-1)
flag=false;
}
puts(flag?"Yes":"No");
}
}
D. 京东牌奶茶
最基本的迷宫,求最短步数,所以bfs一遍即可。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int dx[]= {-1,0,1,0},dy[]= {0,1,0,-1};
char g[15][15];
int sx,sy;
struct point
{
int x,y,cnt;
point(int _x=0,int _y=0,int _cnt=0):x(_x),y(_y),cnt(_cnt) {}
};
int bfs()
{
queue<point> q;
q.push(point(sx,sy,0));
while(!q.empty())
{
point tmp=q.front();
q.pop();
for(int i=0; i<4; ++i)
{
int tx=tmp.x+dx[i],ty=tmp.y+dy[i];
if(g[tx][ty]=='Z')
return tmp.cnt+1;
else if(g[tx][ty]=='*')
{
q.push(point(tx,ty,tmp.cnt+1));
g[tx][ty]='#';
}
}
}
return 0;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
memset(g,'#',sizeof(g));
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
{
scanf(" %c",&g[i][j]);
if(g[i][j]=='L')
{
sx=i;
sy=j;
}
}
int ans=bfs();
ans>0?printf("%d\n",ans):puts("WHERE?!");
}
}
E. Thor的收费站
一开始只是想考查大家的递归,没想到会有人直接用Catalan数来搞。所以放两段代码吧。
#include<cstdio>
using namespace std;
int dfs(int p,int q)
{
if(q==0)
return 1;
if(p<q)
return 0;
return dfs(p-1,q)+dfs(p,q-1);
}
int main()
{
int n;
while(~scanf("%d",&n))
printf("%d\n",dfs(n,n));
}
#include<cstdio>
using namespace std;
const int MAXN=18;
int Catalan[MAXN];
int main()
{
Catalan[0]=0;
Catalan[1]=1;
for(int i=2; i<MAXN; ++i)
Catalan[i]=Catalan[i-1]*(4*i-2)/(i+1);
int n;
while(~scanf("%d",&n))
printf("%d\n",Catalan[n]);
}
F. You-know-what
陈题,当年错误的题目描述不知道坑了多少人。
#include<iostream>
#include<string>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
string str,op,tmp;
int n,x,y;
while(cin>>str>>n)
{
while(n--)
{
cin>>op;
switch(op[0])
{
case 'I':
cin>>x>>tmp;
str.insert(x,tmp);
break;
case 'D':
cin>>x>>y;
str.erase(x,y);
break;
case 'C':
str+=str;
break;
}
}
cout<<str<<endl;
}
}
G. repeat repeat repeat
源自POJ2406,考查对KMP中next数组的理解。不过暴力搞也能过,后缀数组也能搞……但是没必要。
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=1000005;
char str[MAXN];
int next[MAXN];
int main()
{
while(~scanf("%s",str)&&str[0]!='.')
{
int i=-1,j=0,len=strlen(str);
next[0]=-1;
while(j<len)
if(i==-1||str[j]==str[i])
next[++j]=++i;
else
i=next[i];
printf("%d\n",(len%(j-i)==0)?len/(j-i):1);
}
}
基本上就这些了,对我来说没啥特别有趣的题目。