2015浙江财经大学ACM有奖周赛(一) 题解报告

2015浙江财经大学ACM有奖周赛(一) 题解报告

命题:丽丽&&黑鸡

这是命题者原话。

题目涉及的知识面比较广泛,有深度优先搜索、广度优先搜索、数学题、几何题、贪心算法、枚举、二进制等等...

有些题目还需要大家对程序的效率做出优化..大一的小宝宝可能有一些吃不消..当成是一种体验就好了。

题解目录:

ZUFE OJ 2307: 最长连续不下降子串
ZUFE OJ 2308: Lucky Number
ZUFE OJ 2309: 小明爱吃面
ZUFE OJ 2310: 小明爱消除
ZUFE OJ 2311: 找数字
ZUFE OJ 2312: 简单数学题
ZUFE OJ 2313: 字符串还原
ZUFE OJ 2314: 矩形周长
ZUFE OJ 2315: 小明的智力
ZUFE OJ 2316: 水题
ZUFE OJ 2317: 画个圈圈
ZUFE OJ 2318: 跳格子
ZUFE OJ 2320: 高中几何没学好
ZUFE OJ 1606: 清洁公司
ZUFE OJ 2323: 黑鸡跑1000

/*
ZUFE OJ 2307: 最长连续不下降子串
时间复杂度:o(n)
题解:输入a[1]到a[n]
补上a[0]为负无穷大,a[n+1]为无穷大
初始化k为1,ans为0
然后一个一个a[i]扫下去 (1<=i<=n+1)
如果a[i]<a[i-1],那么更新ans=max(ans,k); 
否则k=k+1;
最后ans就是答案
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn=1000000+10;
const int INF=0x7FFFFFFF;
int a[maxn],ans,k,n;

void init()
{
    for(int i=1; i<=n; i++) scanf("%d",&a[i]);
    a[0]=INF;a[n+1]=-INF;
}

void slove()
{
    while(~scanf("%d",&n))
    {
        init();
        ans=0;
        k=1;
        for(int i=1; i<=n+1; i++)
        {
            if(a[i]<a[i-1])
            {
                ans=max(ans,k);
                k=1;
            }
            else k++;
        }
        printf("%d
",ans);
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2308: Lucky Number
题解:设输入的n有x位,设Q等于10的x次方
n*n最后的x位就是 (n*n)%Q
那么只要判断 (n*n)%Q 和 n 是否相等就可以了
要注意的一点就是 0<n<1e9
n*n会超出int范围,所以用long long存储
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

long long n;
long long _n;
long long n2;
int x;//n有x位

void slove()
{
    while(~scanf("%lld",&n))
    {
        _n=n; x=0;
        while(_n) x=x+1, _n=_n/10; //得到n有几位
        if((n*n)%((long long)pow(10.0,x))==n) printf("Yes
");
        else printf("No
");
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2309: 小明爱吃面
时间复杂度:o(n)
题解:一个简单的贪心题
对于第i天,简单的说就是:是今天买,还是之前买?
当然是要选择从第1天到当前天,价格最小的那一天买下今天所需的粮食。

今天吃的价格其实就是之前那些天中最小的价格
处理出每天的价格之后,求和即可。

PS:语文不好...描述的可能不是很清楚。
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn=100000+10;
int a[maxn],p[maxn];
int n,ans;

void init()
{
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i],&p[i]);
    ans=0;
}

void slove()
{
    while(~scanf("%d",&n))
    {
        init();

        for(int i=2;i<=n;i++)
            p[i]=min(p[i-1],p[i]);//找出每一天的价格

        for(int i=1;i<=n;i++)
            ans=ans+a[i]*p[i];

        printf("%d
",ans);
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2310: 小明爱消除
时间复杂度:o(n)
题解:此题属于脑洞题,需要细细咀嚼
      (描述起来比较费劲,略)
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn=1000000+10;
int tot[maxn*2];
int ans,n;

void init()
{
    memset(tot,0,sizeof tot);
    ans=0;
}

void slove()
{
    while(~scanf("%d",&n))
    {
        init();
        for(int i=1; i<=n; i++)
        {
            int x;
            scanf("%d",&x);
            tot[x]++;
        }
        int k=0,m;
        while(k<2*maxn)
        {
            m=tot[k]/2;
            tot[k]=tot[k]%2;
            tot[k+1]=tot[k+1]+m;
            k++;
        }
        for(int i=0; i<2*maxn; i++)
            ans=ans+tot[i];
        printf("%d
",ans);
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2311: 找数字
时间复杂度:o(n*n)
题解:开一个数组记录每个数字有几个
      tot[x]=y 代表x有y个!
      然后两层循环枚举B和C
      枚举到的时候 tot[B]--,tot[C]--;
      然后验证tot[B+C]是否大于0,即A是否存在
      大于零则表示存在。
      否则不存在。
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn=1000+10;
int tot[maxn],a[maxn];
int n;

void slove()
{
    while(~scanf("%d",&n))
    {
        memset(tot,0,sizeof tot);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            tot[a[i]]++;
        }
        int ans=0;
        for(int i=1; i<=n; i++)
        {
            for(int j=i+1; j<=n; j++)
            {
                tot[a[i]]--;
                tot[a[j]]--;
                if(tot[a[i]+a[j]]>0)
                {
                    ans=1;
                    break;
                }
                tot[a[i]]++;
                tot[a[j]]++;
            }
            if(ans==1) break;
        }
        if(ans==0) printf("NO
");
        else printf("YES
");
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2312: 简单数学题
题解:数学题,a的b次方和c的d次方都很大,直接判断是做不出来的。
如果我们能找到一个函数F(x)是单调的,
而F(X)的值又比较好算,那么可以通过比较F(X)的大小来判断自变量的大小。

令F(X)=log(X),a的b次方和c的d次方当做自变量。
那么接下来只要判断log(a的b次方)和log(c的d次方)的大小
就可以判断a的b次方和c的d次方的大小了。

而log(a的b次方)=b*log(a),log(c的d次方)=d*log(c),很容易计算。

判断相等的时候注意一下精度问题。
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

double a,b,c,d;

int main()
{
    while(~scanf("%lf%lf%lf%lf",&a,&b,&c,&d))
    {
        double ans1=b*log(a);
        double ans2=d*log(c);

        if(fabs(ans1-ans2)<0.000001) printf("=
");
        else if(ans1>ans2) printf(">
");
        else printf("<
");
    }
    return 0;
}
/*
ZUFE OJ 2313: 字符串还原
时间复杂度:o(n)
题解:水题,搞之...
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn=100+10;
char s[maxn];
int T;

void slove()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        int len=strlen(s);
        for(int i=0;i<len;i++)
            if(i%2==0) printf("%c",s[i]);
        printf("
");

        for(int i=len-1;i>=0;i--)
            if(i%2==1) printf("%c",s[i]);
        printf("
");
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2314: 矩形周长
时间复杂度:o(sqrt(n))
题解:枚举一下边长就可以了
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int INF=0x7FFFFFFF;
int T,n;

void slove()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int MaxL=sqrt(1.0*n);
        int ans=INF;
        for(int i=1;i<=MaxL;i++)
        {
            if(n%i!=0) continue;
            else
            {
                if(2*(i+n/i)<ans)
                    ans=2*(i+n/i);
            }
        }
        printf("%d
",ans);
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2315: 小明的智力
时间复杂度:o(n)
题解:简单的贪心题
      先排序,然后吃2,最后吃1
      找到第一个比p大的位置
      从这个位置开始吃2,吃完2 最后吃1
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn=1000+10;
int a[maxn];
bool flag[maxn];
int T,n,p;

void slove()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(flag,0,sizeof flag);
        scanf("%d%d",&n,&p);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        int now=n+1;
        for(int i=1;i<=n;i++)
        {
            if(a[i]>p)
            {
                now=i;
                break;
            }
        }
        
        for(int i=now;i<=n;i++)
            if(a[i]>p)
                flag[i]=1,p=p+2;

        for(int i=1;i<=n;i++)
            if(flag[i]==0) p=p+1;
        printf("%d
",p);
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2316: 水题
时间复杂度:o(n)
题解:水题,搞之...
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int INF=0x7FFFFFFF;
const int maxn=100000+10;
int T,ans,n;
int a[maxn];

void slove()
{
    scanf("%d",&T);
    while(T--)
    {
        ans=-INF;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=2;i<=n;i++)
            if(a[i]-a[i-1]>ans)
                ans=a[i]-a[i-1];
        printf("%d
",ans);
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2317:画个圈圈
*/
#include<stdio.h>
#include<math.h>
#include<map>
#include<algorithm>
#include<string.h>
using namespace std;
   
const int maxn=10+10;
int ans,N,M;
char Map[maxn][maxn];
bool flag[maxn][maxn];
char sign;
int dir[4][2]= {{-1,0},{1,0},{0,-1},{0,1}};
   
void init()
{
    memset(flag,0,sizeof flag);
    ans=0;
}
   
void dfs(int x,int y,int Dir)
{
    if(flag[x][y]==1&&Dir!=-1)
    {
        ans=1;
        return;
    }
    flag[x][y]=1;
    for(int i=0; i<4; i++)
    {
        int NewX=x+dir[i][0];
        int NewY=y+dir[i][1];
   
        if(Dir==0&&i==1) continue;
        if(Dir==1&&i==0) continue;
        if(Dir==2&&i==3) continue;
        if(Dir==3&&i==2) continue;
        if(Map[NewX][NewY]!=sign) continue;
        if(NewX<0||NewX>=N) continue;
        if(NewY<0||NewY>=M) continue;
   
        dfs(NewX,NewY,i);
        if(ans) return;
    }
}
   
void slove()
{
    while(~scanf("%d%d",&N,&M))
    {
        for(int i=0; i<N; i++)
            scanf("%s",Map[i]);
        init();
        for(int i=0; i<N; i++)
        {
            for(int j=0; j<M; j++)
            {
                sign=Map[i][j];
                memset(flag,0,sizeof flag);
                dfs(i,j,-1);
                if(ans) break;
            }
            if(ans) break;
        }
        if(ans==1) printf("Yes
");
        else printf("No
");
    }
}
   
int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2318: 跳格子
时间复杂度:不会算
题解:BFS
*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;

const int INF=0x7FFFFFFF;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
const int maxn=300+10;
int N,M,ans;
int Sx,Sy,Ex,Ey;
int Map[maxn][maxn];
int flag[maxn][maxn];
struct Point
{
    int x,y;
    int tot;
};
queue<Point>Q;

void BFS()
{
    while(!Q.empty()) Q.pop();
    for(int i=0;i<maxn;i++)
        for(int j=0;j<maxn;j++)
            flag[i][j]=INF;
    Point p;
    p.x=Sx; p.y=Sy; p.tot=0;
    Q.push(p);
    ans=-1;
    flag[Sx][Sy]=0;
    while(!Q.empty())
    {
        Point h=Q.front(); Q.pop();
        if(h.x==Ex&&h.y==Ey)
        {
            ans=h.tot;
            break;
        }
        for(int i=0;i<4;i++)
        {
            int NewX=h.x+dir[i][0];
            int NewY=h.y+dir[i][1];

            if(NewX>=1&&NewX<=N)
            {
                if(NewY>=1&&NewY<=M)
                {
                    if(Map[NewX][NewY]!=3)
                    {
                        if(flag[NewX][NewY]>h.tot+1)
                        {
                            flag[NewX][NewY]=h.tot+1;
                            Point x;
                            x.x=NewX;
                            x.y=NewY;
                            x.tot=h.tot+1;
                            Q.push(x);
                        }
                    }
                }
            }
        }
    }
    printf("%d
",ans);
}

void slove()
{
    while(~scanf("%d%d",&N,&M))
    {
        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++)
                scanf("%d",&Map[i][j]);

        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++)
            {
                if(Map[i][j]==1) Sx=i,Sy=j;
                if(Map[i][j]==2) Ex=i,Ey=j;    
            }

        BFS();
    }
}

int main()
{
    slove();
    return 0;
}
/*
ZUFE OJ 2320: 高中几何没学好
时间复杂度:o(1)
题解:连接AX
      设三角形AFX面积为e,三角形AXE面积为f
      得到三个方程
      e+f=d
      f/c=(a+d)/(b+c)
      e/a=(c+d)/(a+b)
      三个未知量都可以解出来
*/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

double a,b,c,k;
double e,f;

int main()
{
    while(~scanf("%lf%lf%lf",&a,&b,&c))
    {
        k=(a+b)/(b+c);
        f=(a*c)/(b-c*k);
        e=k*f;
        printf("%.4lf
",e+f);
    }
    return 0;
}
/*
ZUFE OJ 1606: 清洁公司
题解:DFS求连通块
*/
#include<stdio.h>

char gird[105][105];
int m,n;
int dir[8][2]= {{-1,-1},{-1,0},{-1,1},{0,1}
    ,{1,1},{1,0},{1,-1},{0,-1}};

void dfs(int x,int y)
{
    int i,xx,yy;
    gird[x][y]='#';
    for(i=0; i<8; i++)
    {
        xx=x+dir[i][0];
        yy=y+dir[i][1];
        if(xx<0||yy<0||xx>=m||yy>=n) continue;
        if(gird[xx][yy]=='@') dfs(xx,yy);
    }
}
int main()
{
    int i,j;
    int count;
    while( scanf("%d%d",&m,&n)!=EOF)
    {
        for(i=0; i<m; i++) scanf("%s",gird[i]);
        count=0;
        for(i=0; i<m; i++)
        {
            for(j=0; j<n; j++)
            {
                if(gird[i][j]=='@')
                {
                    dfs(i,j);
                    count++;
                }
            }
        }
        printf("%d
",count);
    }
    return 0;
}
/*
ZUFE OJ 2323: 黑鸡跑1000
题解:水题..搞之..
*/
#include <stdio.h>

double a,b;

int main()
{
    while(~scanf("%lf%lf",&a,&b))
        printf("%.2lf
",500.0/a+500.0/b);
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/4941760.html