2016 Multi-University Training Contest 3 解题报告

来源:互联网 发布:笔记本电脑录视频软件 编辑:程序博客网 时间:2024/06/05 12:05

1.1001-HDU 5752 Sqrt Bo

题意:给你一个整数n,问你需要经过几次开根号并向下取整的操作,使得值为1,超过5次输出"TAT"。

题解:开根号向下正得到1的最大的数为3.9999999……(约等于2^2),开根号向下取整得到4(2^2)的最大的数为15.9999999……(约等于2^4),…………可以得到能在五次之内开根取整得到1的最大值为2^32.

先判断边界是否超过2^32(大约42亿)。然后暴力开根即可。注意特判0.

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<cmath>using namespace std;typedef long long LL;int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    string s;    while(cin>>s)    {        if(s.size()<=10)        {            LL num=0;            for(int i=0;i<s.size();i++)            {                num=num*10+(s[i]-'0');            }            if(num==0) printf("TAT\n");            else             {                int cnt=0;                while(num>=1)                {                    num=(LL)sqrt(num);                    cnt++;                    if(num==1) break;                }                if(cnt<=5)                    printf("%d\n",cnt);                else                     printf("TAT\n");            }        }        else             printf("TAT\n");    }    return 0;}

2.1002-HDU 5753 Permutation Bo

题意:是1-n的一个排列,,给你一个序列,求函数的期望值。

题解:我们考虑这个排列的每一及其贡献值,所以我们可以求出每一位上满足条件排列总数,然后除以排列总数(n!)即可求出期望。

考虑第一位和最后一位 ,满足中间大于两边的排列数为C(n,2)*(n-2)!=A(n,n-2)=n!/2。(从n个数中任选两个数,这两个数排列只能有一种情况,在乘上其余n-2个数 的全排列)

考虑中间的位置,满足中间大于两边的排列数为C(n,3)*2*(n-3)!=A(n,n-3)*2=n!/3。(从n个数中任选三个数,这三个数排列能有两种情况,在乘上其余n-3个数 的全排列)

两种情况加起来除以排列总数(n!)可以得到,两个边界的贡献度为 Ci 除以2,中间的数为 Ci 除以3。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAX=1000+10;int a[MAX];int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n;    while(scanf("%d",&n)!=EOF)    {        for(int i=0;i<n;i++)        {            scanf("%d",&a[i]);        }        int tmp=0;        for(int i=1;i<n-1;i++)            tmp+=a[i];        double ans=(a[0]+a[n-1])/2.0+tmp/3.0;        printf("%.6lf\n",ans);    }    return 0;}

3.1010-HDU 5761 Rower Bo

题意:小船过河问题。

水流方向沿x轴,小船初始位置在 (0,a) ,终点在(0,0),小船的船头即船的速度方向始终指向(0,0),求到达终点的时间。

题解:

小船相当于有了一条类似抛物线的路径。对中间某一时刻分析。



比赛的时候只想到列x方向和y方向,没想到斜向分解,这样列出方程巧妙的消掉的未知参数(那个角度)。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int a,v1,v2;    while(scanf("%d%d%d",&a,&v1,&v2)!=EOF)    {        if(a==0) printf("0.0000000000\n");        else         {            if(v1<=v2) printf("Infinity\n");            else            {                printf("%.10lf\n",1.0*v1*a/(v1*v1-v2*v2));            }        }    }    return 0;}

4.1011-HDU 5762 Teacher Bo

题意:给你一堆点,判断是否有一个四元组(A,B,C,D)(A<B,C<D,A≠CorB≠D)使得A到B的 哈密顿距离等于C到D的哈密顿距离。

题解:暴力枚举两两点对,并记录其距离是否访问过。遇到访问过的距离直接退出输出YES,否则输出NO。

由于坐标范围有限,所以最大的复杂度是不会超过M的(鸽巢原理)。每组数据的负载度为O(min(N^2,M))。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAX=100000+10;struct point {    int x,y;    point(int _x=0,int _y=0):x(_x),y(_y){};};point p[MAX];int vis[MAX*2];int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int T;    scanf("%d",&T);    while(T--)    {        int n,m;        scanf("%d%d",&n,&m);        for(int i=0;i<n;i++)        {            scanf("%d%d",&p[i].x,&p[i].y);        }        memset(vis,0,sizeof(vis));        int flag=0;        for(int i=0;i<n&&!flag;i++)        {            for(int j=i+1;j<n;j++)            {                int dis=abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y);                if(vis[dis])                {                    flag=1;                    break;                }                vis[dis]=1;            }        }        printf("%s\n",flag?"YES":"NO");    }    return 0;}


0 0
原创粉丝点击