bupt暑假排位赛(1)

    (PS:今天搞octopress搞了一天,还是没有搞定,到了9点半实在不行了,就暂时放弃了。。。) 

    这次的题目,怎么说呢,用“只有你想不到的,没有你做不到。”的来形容实在是再好不过了。

A( BOJ 413 学姐的桌面)很水的一题,不过有些坑。

    题意大概是,学姐偷到了360内部的用户开机时间的数据,给了你学姐的开机时间和偷到的所有n个用户的开机时间,问你学姐的开机时间比多少用户快;

    坑就坑在那个开机时间上,谁知道他的开机时间竟然是越大越快!!不小心看测试数据的话,就会掉进坑里。代码如下

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
 
#define N 100005
using namespace std;
 
int a[N];
 
int main()
{
    int T;
    cin>>T;
    while (T--)
    {
        memset(a,0,sizeof(0));
        int n,t;
        int cnt=0;
        scanf("%d%d",&n,&t);
        for (int i=1;i<=n;i++)
        {
            int m;
            scanf("%d",&m);
            if (t>m) cnt++;
        }
        double ans=((double)cnt/n)*100.00;
        printf("%.2lf",ans);
        cout<<"%"<<endl;
    }
 
}

 

B(BOJ0414 学姐去学车)一个逻辑问题,逻辑理清楚了就简单了

    题意是,学姐去学车,有两个教练轮流教,这两个教练都是连续上班n天之后放一天的假,当前教学姐的教练放假后,换另外一个教练,一直教到这个教练放假,再换回原来那个教练。教练1从第1天开始教学姐(当做之前一天刚放完假),教练2第m天放假(1<=m<=n),问你第day天是哪个教练教学姐。(数据是1e9以内)

    很容易就发现,因为教练的放假时间和上班时间是相同的,所以这肯定是一个循环的问题。循环节是多少呢?每个教练上班n天,然后再放假1天,很明显,循环节应该是(n+1)所以,我们可以列一下每个教练放假的时间,

               教练1             教练2           根据左边,很容易                 教练1           教练2

                0                 m             知道教练的上班时                 [1,n]          [n+1,n+m]

               n+1               n+1+m          间                           [n+m+1,2n+1]      [2n+2,2n+1+m]

              2n+2              2n+2+m                                       [2n+2+m,3n+2]     [3n+3,3n+2+m]

              3n+3              3n+3+m                                           .                 .

                .                  .                                             .                 .

 右边的区间对n+1取余,就会发现,除了第一个区间,都有教练1[m,n] 教练2 [0,m-1]

综上,很容易得出结果,下面附代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
 
#define N 100005
using namespace std;
 
 
 
int main()
{
   int t;
   cin>>t;
   while (t--)
   {
       int n,m;
       int coatch=1;
       scanf("%d%d",&n,&m);
       int q;
       scanf("%d",&q);
       for (int i=1;i<=q;i++)
       {
           int day;
           scanf("%d",&day);
           if (day==0) coatch=2;
           else if (day>=1&&day<=n) coatch=1;
           else
           {
               int mod=day%(n+1);
 
               if (mod>=0&&mod<m) coatch=2;
               else coatch=1;
           }
           printf("%d\n",coatch);
       }
   }
 
}

 

C(boj 0415 学姐的学弟)忽略了一个条件,就把简单题编程难题了。

      题意是给你n个单位圆的坐标(为整点且大于1小于100),求这n个单位圆的总面积。

      做题中自动忽略了坐标都是整数这个东西,结果。。。你懂得。

     由于坐标都是整数,所以对于每一个单元格,都只有4中情况,空,满,1/4圆 和 2个弧分别过彼此圆心的 1/4圆。只要把这四种状态的面积求出来,然后对每个单元格进行判断求和即可

    继续附代码

 

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
 
#define pi 3.141592653
 
using namespace std;
 
int main()
{
    double s=(pi/3.0)*2.0-sqrt(3.0)*0.5,s1=pi/2-s/2,s2=1.0,s3=pi/4;
    int t;
    int dx[]={1,1,0,0},dy[]={0,1,0,1};
 
    cin>>t;
 
    while (t--)
    {
        bool judge[105][105]={false};
        int maxx=0,maxy=0,minx=105,miny=105;
        int n;
        double ans=0;
 
        scanf("%d",&n);
 
        for (int i=1;i<=n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            judge[x][y]=true;
            maxx=max(maxx,x+1);
            maxy=max(maxy,y+1);
            minx=min(minx,x-1);
            miny=min(miny,y-1);
        }
        for (int i=minx;i<maxx;i++)
            for (int j=miny;j<maxy;j++)
            {
                int pointNum=0;
                for (int k=0;k<4;k++)
                    if (judge[i+dx[k]][j+dy[k]]) pointNum++;
                if (pointNum>=3) ans+=s2;
                else if(pointNum==1) ans+=s3;
                else if(pointNum==2)
                {
                    if (judge[i][j]&&judge[i+1][j+1]||judge[i][j+1]&&judge[i+1][j])
                        ans+=s2;
                    else ans+=s1;
                }
            }
        printf("%.5lf\n",ans);
    }
}


D(BOJ 407 BLOCKS) 一个搜索题,题意如下

    给定一个n*m的矩阵,求问里面有多少个由'#'组成的矩形,若是里面有一个不是矩形的联通块,则输出"So Sad",数据时1000以内的.

    时间上来说,搜索过是绰绰有余的。不过要注意一点,这个数据如果裸dfs的话,会堆栈溢出(1000*1000层)。

   我用的是DFS,优化了下,思路如下。

   找出每一块#区域的横纵坐标最大值和最小值(不管a[maxx,maxy] ,a[minx,miny]是否也是#);然后再在每个记录的区域内搜索,如果碰到不是#的,结果就应该是So Sad;    如果所有的#区域中都只有#,就输出#区域的个数。

   DFS的剪枝是,只搜索每个#区域的边界(向外扩散),不用搜索内部(但是需要标记内部),因为我的搜索要记录的只是#区域的最大最小横纵坐标,所以可以这样做(内部的坐标肯定大于或者小于外部的),具体实现我就不赘述了,看代码应该能看懂吧!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#define N 1005
using namespace std;
 
struct data
{
    int maxx;
    int maxy;
    int minx;
    int miny;
};
char board[N][N];
 
vector <data> rec;
vector <pair<int,int> > jingRec;
 
int n,m;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
bool haveSearch[N][N];
 
void dfs(int x,int y,bool judge)
{
    if (x<0||y<0||x>=n||y>=m) return;
    if(haveSearch[x][y]) return;
    haveSearch[x][y]=true;
    if (judge) rec.push_back({x,y,x,y});
    int sz=rec.size()-1;
 
    int xx=x,yy=y;
    while (board[xx+1][y]=='#')
    {
        xx++;
        haveSearch[xx][y]=true;
    }
    while (board[x][yy+1]=='#')
    {
        yy++;
        haveSearch[x][yy]=true;
    }
    if (rec[sz].maxx<xx) rec[sz].maxx=xx;
    if (rec[sz].minx>x) rec[sz].minx=x;
    if (rec[sz].maxy<yy) rec[sz].maxy=yy;
    if (rec[sz].miny>y) rec[sz].miny=y;
 
    for (int i=x;i<=xx;i++)
    {
        if (board[i][y-1]=='#') dfs(i,y-1,false);
        if (board[i][yy+1]=='#') dfs(i,yy+1,false);
    }
     for (int i=y;i<=yy;i++)
    {
        if (board[x-1][i]=='#') dfs(x-1,i,false);
        if (board[xx+1][i]=='#')dfs(xx+1,i,false);
    }
 
}
 
int main()
{
 
   while (~scanf("%d%d",&n,&m))
   {
        bool judge=false;
        memset(board,0,sizeof(board));
        memset(haveSearch,false,sizeof(haveSearch));
        jingRec.clear();
        rec.clear();
 
        for (int i=0;i<n;i++)
        {
            scanf("%s",board[i]);
            for (int j=0;j<m;j++)
                if (board[i][j]=='#') jingRec.push_back({i,j});
        }
 
        for (int i=0;i<jingRec.size();i++)
        {
            bool needRec=!haveSearch[jingRec[i].first][jingRec[i].second];
            dfs(jingRec[i].first,jingRec[i].second,true);
            if (needRec)
            {
                int k=rec.size()-1;
                for (int i=rec[k].minx;i<=rec[k].maxx;i++)
                    for (int j=rec[k].miny;j<=rec[k].maxy;j++)
                        haveSearch[i][j]=true;
            }
        }
 
        for (int k=0;k<rec.size();k++)
        {
            if (judge) break;
            for (int i=rec[k].minx;i<=rec[k].maxx;i++)
                for (int j=rec[k].miny;j<=rec[k].maxy;j++)
                    if (board[i][j]!='#')
                    {
                        judge=true;
                        break;
                    }
        }
        if (judge) printf("So Sad\n");
        else printf("There are %d ships.\n",rec.size());
 
   }
 
}


    E题,由于C++的大数敲起来太麻烦了,虽然找了个模板,但是也不想用了,打算近一个星期吧,抽些时间学学Java,然后再找几道大数的题练一练。

   关于这题的题解,一种思路可以去参考下syx童鞋的这个博客,他那里还提到了另外一个博客,博主叫fisher_jiang(题目链接请点名字),那里有题目的描述和解题方法,我的思路跟他的差不多(当然,是有漏洞的,看了他的题解以后才明白错在哪里了),这个题的题解我也就不写了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值