A题:中学物理题,直接求就好了;
#include<stdio.h> #include<string.h> int main() { __int64 cas,s,h,vx,vy; scanf("%I64d",&cas); while(cas--) { scanf("%I64d%I64d%I64d%I64d",&s,&h,&vx,&vy); vx=s/vx; vy=vy*vx-5*vx*vx; if(vy>=h) puts("good done!"); else puts("poor Merida!"); } return 0; }
#include<stdio.h> #include<string.h> char substr[110]; int next[110]; char tolower(char ch) { if(ch>='A'&&ch<='Z') return ch-'A'+'a'; return ch; } void get(int m) { int i=-1,j=0;next[0]=-1; while(j<m){ if(i==-1||tolower(substr[i])==tolower(substr[j])) { i++;j++; next[j]=i; }else i=next[i]; } } char str[55000]; int kmp(int s,int m,int n) { int i=s,j=0; while(i<n&&j<m){ if(j==-1||tolower(str[i])==tolower(substr[j])){ i++;j++; }else j=next[j]; } return j<m?-1:i-m; } char des[110]; int main() { int i,n,m,k,g; while(scanf("%s",substr)!=EOF) { m=strlen(substr);get(m); getchar(); gets(des);g=strlen(des); gets(str);n=strlen(str); for(i=0;i<n;){ k=kmp(i,m,n); if(k==-1){ printf("%s",str+i); i=n; }else { for(;i<k;i++) putchar(str[i]); i=k+m; for(k=0;k<g;k++) putchar(des[k]); } } putchar('\n'); } return 0; }
#include<stdio.h> #include<string.h> int a[]={1,0,0,0,1,0,1,0,2,1}; int main() { int cas,n,sum; scanf("%d",&cas); while(cas--) { sum=0; scanf("%d",&n); while(n) sum+=a[n%10],n/=10; printf("%d\n",sum); } return 0; }
D题:搜索
/*
* 题目:吃豆人
* 题目链接:http://acm.fzu.edu.cn/contest/problem.php?cid=129&sortid=4
* 题目描述:
* 地图上有n×m个格子,每格地形可能为空地或者障碍物,吃豆人可以在空地上移动,
* 吃豆人每移动一格需要1s时间,并且只能朝上下左右四个方向移动,特别的是吃豆人还能吐出舌头,
* 舌头每移动一格需要0.1s时间,舌头只可以走直线。不必考虑吃豆人转身所需要的时间。
* 游戏中还有加速道具,一旦得到加速道具,吃豆人就获得2倍移动速度,吐舌头的速度没有增加,
* 即走1格用0.5s。现在地图上有且只有一颗豆子。游戏中有.代表空地;X表示障碍,吃豆人不能越过障碍;
* B代表豆子;S代表加速道具,并且地图上道具总数不超过1个,道具所在的位置为空地,得到道具后立即使用,
* 道具立即消失,地形变为空地,不能用舌头去取道具;P表示吃豆人,吐舌头的时候吃豆人不能移动。
* 求最快用多少s吃到豆子,结果保留1位小数?
*
* 解题思路:
* 和往常用bfs去搜索一条最优的路径的做法一样,这个也可以采用bfs搜索,因为数据范围很小用dfs也可以;
* 我是用bfs做的,用dp[i][j][s]表示从起点走到(i,j)点且当前速度为s的最短时间,这样不断的去更新所有
* 点,在每一点上都尝试是否可以吃到豆子,如果可以吃到豆子,则去尝试更新吃豆子的最短时间,这样直到队列为空。
*
* 最后如果可以吃到豆子,输出能吃到豆子的最短时间,否则输出-1;
* 代码如下:
*/
#include<stdio.h> #include<string.h> #include<queue> using namespace std; int op[4][2]={1,0,0,1,-1,0,0,-1}; char mat[30][30]; int n,m; int dp[30][30][15],vis[30][30][15]; void update(int r,int c,int s,int &Min) //判断是否可以吃到豆子,并去更新最短时间 { int i; for(i=r+1;i<=n;i++) if(mat[i][c]!='.'&&mat[i][c]!='S')break; if(i<=n&&mat[i][c]=='B'&&dp[r][c][s]+(i-r)*2<Min) Min=dp[r][c][s]+(i-r)*2; for(i=r-1;i>0;i--) if(mat[i][c]!='.'&&mat[i][c]!='S')break; if(i>0&&mat[i][c]=='B'&&dp[r][c][s]+(r-i)*2<Min) Min=dp[r][c][s]+(r-i)*2; for(i=c+1;i<=m;i++) if(mat[r][i]!='.'&&mat[r][i]!='S') break; if(i<=m&&mat[r][i]=='B'&&dp[r][c][s]+(i-c)*2<Min) Min=dp[r][c][s]+(i-c)*2; for(i=c-1;i>0;i--) if(mat[r][i]!='.'&&mat[r][i]!='S') break; if(i>0&&mat[r][i]=='B'&&dp[r][c][s]+(c-i)*2<Min) Min=dp[r][c][s]+(c-i)*2; } int bfs(int r,int c) //搜索函数 { int i,j,x,y,Min=10000000,s,ts,k; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) for(k=1;k<=10;k++) dp[i][j][k]=100000000; queue<int> X,Y,S; vis[r][c][10]=1;dp[r][c][10]=0; X.push(r);Y.push(c);S.push(10); while(!X.empty()){ r=X.front();X.pop(); c=Y.front();Y.pop(); s=S.front();S.pop(); update(r,c,s,Min); for(i=0;i<4;i++) //往4个方向搜 { ts=s; x=r+op[i][0]; y=c+op[i][1]; if(x<1||x>n||y<1||y>m||mat[x][y]=='X'||(mat[x][y]=='S'&&s==5)) continue; if(mat[x][y]=='S') ts=s/2; if(dp[r][c][s]+s<dp[x][y][ts]){ dp[x][y][ts]=dp[r][c][s]+s; update(x,y,ts,Min); if(!vis[x][y][ts]){ vis[x][y][ts]=1; X.push(x);Y.push(y);S.push(ts); } } } vis[r][c][s]=0; } if(Min==10000000) Min=-1; return Min; } int main() { int i,j,sx,sy; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++) scanf("%s",mat[i]+1); for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(mat[i][j]=='P'){ sx=i;sy=j;} sy=bfs(sx,sy); if(sy<0) printf("-1\n"); else printf("%.1lf\n",sy/10.0); } return 0; }
E题:看懂题意的公式后,s(x,m)的范围不会超过1000,所以x的取值范围就在sqrt(n)至sqrt(n)-1000左右,
解释:因为s(x,m)的最大值不会超过1000,当x为(sqrt(n)-1000)以下时,x*(x+s(x,m))<sqrt(n)×sqrt(n)<n;所以就不可能了
枚举几百上千次就好了。
#include<stdio.h> #include<math.h> #include<string.h> #define _LL __int64 #define FM "%I64d" int m; _LL F(_LL x) { _LL t=x,sum=x*x; while(x){ sum+=(x%m)*t;x/=m; } return sum; } int main() { int cas; _LL n,i,l; scanf("%d",&cas); while(cas--){ scanf(FM,&n); scanf("%d",&m); l=(_LL)sqrt((double)(n+1));i=l-1000; if(i<=0)i=1; for(;i<=l;i++) if(F(i)==n) break; if(i>l) i=-1; printf("%d\n",(int)i); } return 0; }
F题:不会
G题:枚举第一条边的长度,统计当第一条边确定时,第二三条边可能的方案数;
三角形的二三条边中,令第二条边慢慢增大,第三条边慢慢减小,所以当第一边确定时的答案就是:
Min(第二条可以增大的最大值,第三条可以减小的最大值,第三条边的上限减去第二条边的下限除以2);
H题:用ac自动机求出母串每一个匹配点的向前的最短匹配距离,然后求出母串每一个点的向前的最大合法长度,取所有中的最大值就是答案;
这题貌似用后缀数组也可以解;
#include<stdio.h> #include<string.h> #include<queue> using namespace std; #define N 101000 int ch[N][26],cnt,f[N],last[N],val[N],pos[N]; struct aho_corasick { aho_corasick(){ cnt=0; memset(ch,0,sizeof(ch)); memset(val,0,sizeof(val)); memset(pos,0,sizeof(pos)); } int newnode(){ return ++cnt; } int idx(char c){ return c-'a'; } void insert(char *s,int n) { int root=0,i; for(i=0;i<n;i++) { int u=idx(s[i]); if(!ch[root][u])ch[root][u]=newnode(); if(i==n-1) val[ch[root][u]]=n; root=ch[root][u]; } } void getfail() { queue <int> q; f[0]=0; int i,u; for(i=0;i<26;i++) { u=ch[0][i]; if(u){ f[u]=0; q.push(u);last[u]=0; } } while(!q.empty()) { int r=q.front(); q.pop(); for(i=0;i<26;i++) { u=ch[r][i]; if(!u){ ch[r][i]=ch[f[r]][i]; continue; } q.push(u); int v=f[r]; while(v&&!ch[v][i]) v=f[v]; f[u]=ch[v][i]; last[u]=val[f[u]]?f[u]:last[f[u]]; } } } int find(char *t,int n) { int i,j=0,temp; for(i=0;i<n;i++) { int c=idx(t[i]); //while(j&&!ch[j][c])j=f[j]; j=ch[j][c]; temp=j; while(temp) { if(val[temp]&&(!pos[i]||val[temp]<pos[i])) pos[i]=val[temp]; temp=last[temp]; } } return 0; } }; char str[1100000],substr[110]; int main() { int i,n,len; while(scanf("%s",str)!=EOF) { len=strlen(str); scanf("%d",&n); aho_corasick ac; for(i=1;i<=n;i++) { scanf("%s",substr); ac.insert(substr,strlen(substr)); } ac.getfail(); ac.find(str,len); //for(i=0;i<len;i++)printf("%d",pos[i]); //printf("\n"); if(!pos[0])pos[0]=2; for(i=1,n=0;i<len;i++) { if(!pos[i]) pos[i]=pos[i-1]+1; else{ if(pos[i]>i-n+pos[n]) pos[i]=i-n+pos[n]; n=i; } } //for(i=0;i<len;i++)printf("%d",pos[i]); //printf("\n"); for(n=i=0;i<len;i++) if(pos[i]>n) n=pos[i]; printf("%d\n",n-1); } return 0; }
I题:不会