zoukankan      html  css  js  c++  java
  • 2016 Multi-University Training Contest 3

    5/11

    2016 Multi-University Training Contest 3
    官方题解

    2016年多校训练第三场 老年选手历险记

    暴力 A Sqrt Bo(CYD)

    题意:
    问进行多少次开根号向下取整能使给定的值为1,若为5次以上,则输出TAT;

    思路:

    有5次这个限制,得知值最大为10的11次方左右,存下后运算即可,注意初始值为0时运算的次数是大于5次的,输出TAT;

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    char str[105];
    
    int main()
    {
        int i,j,k;
        while(scanf("%s",str)!=EOF)
        {
            double ans=0;
            int l=strlen(str);
            if(l>12 || (l==1 && str[0]=='0'))
            {
                printf("TAT
    ");
                continue;
            }
            for(i=0;i<l;i++)
            {
                ans=ans*10;
                ans+=str[i]-'0';
            }
    
            int cnt=0;
            while(ans-1.0>=1e-6)
            {
                ans=floor(sqrt(ans));
                cnt++;
            }
            if(cnt>5)
                printf("TAT
    ");
            else
                printf("%d
    ",cnt);
        }
        return 0;
    }
    

    线性期望 B Permutation Bo(BH)

    题意:

      有n个数字,范围1~n,对于一个排列,有已知,后面意思是判断大于左右两边的数字,结果1或0,然后与相乘累加,求对于全排列,f(h)的期望值。

    思路:

      对于这种线性期望题,对于每一个,求它能贡献的概率*权值,权值已知,也就是要求在全排列出现的概率。易得概率为,答案为

    代码:

    #include <bits/stdc++.h>
    
    const int N = 1e3 + 5;
    int c[N];
    
    int main() {
        int n;
        while (scanf ("%d", &n) == 1) {
            int s1 = 0, s2 = 0;
            for (int i=1; i<=n; ++i) {
                scanf ("%d", c+i);
                if (i == 1 || i == n) s1 += c[i];
                else s2 += c[i];
            }
            double ans = 0;
            if (n == 1) {
                ans = c[1];
            } else {
                ans = (double) s1 / 2 + (double) s2 / 3;
            }
            printf ("%.6f
    ", ans);
        }
        return 0;
    }

    博弈/打表 Life Winner Bo(BH)

    题意:

      n*m的棋盘,在(1,1)的位置放一个国际象棋中的棋子(国王,车,骑士,皇后),国王相当于中国象棋的士的走法,车就是车,骑士相当于马(没有马脚),皇后有士的方向,车的距离。每次只能往右下走,B先走,问谁必胜。

    思路:

      反思:一开始我就想用从下往上递推状态图,写了四个函数分别是四个棋子的走法,对于车和皇后的后继状态比赛时先用了树状数组T了,后来用了数组求前缀后省了logn,但还是T了,一脸懵逼。后来才发现T<=1000,再加上我每次都的跑,不T才怪。后来脑子清醒点再加上队友的指点,才想到还有预处理这条路,存下所有4*n*m的结果,然后输出答案,结果还是以WA终场。赛后知道皇后是经典的威佐夫博弈,完全没听说过,博弈只会简单的递推。。。,

      看完题解知道车原来就是经典的Nim,至于另外两个可以打表找规律也可以直接递推的。经检验,比赛的递推代码里只有皇后是有问题的,补题时打表找出马和国王的规律。代码里还留有递推的正确代码。

      另外,只有马有平局的情况,出现这种可能的局面是B在没有必胜的可能情况下,平局比必败优,选择走平局的情况(往不能走的边界方向走)。

    代码:

    #include <bits/stdc++.h>
    
    const int N = 1e3 + 5;
    const int W = 1e3;
    const double a = (sqrt (5.0) + 1) / 2;
    int win[N][N];
    int dp[4][N][N];  //1 2 3
    int row[N][N], col[N][N];
    int tp, n, m;
    
    void debug() {
        for (int i=1; i<=20; ++i) {
            for (int j=1; j<=20; ++j) {
                printf ("%c ", dp[3][i][j]);
            }
            puts ("");
        }
    }
    
    char solve_rook() {
        return (n ^ m) ? 'B' : 'G';
    }
    
    char solve_queen() {
        if (n > m) std::swap (n, m);
        n--; m--;
        int k = m - n;
        if (n == (int) (a * k)) return 'G';
        else return 'B';
    }
    
    char solve_king() {
        if (n & 1 && m & 1) return 'G';
        else return 'B';
    }
    
    char solve_knight() {
        if (n == m) {
            if (n % 3 == 1 && n >= 4) return 'G';
            else return 'D';
        } else {
            if (n > m) std::swap (n, m);
            if (n + 1 == m && n % 3 == 2 && n >= 2) return 'B';
            else return 'D';
        }
    }
    
    void init() {
        n = m = W;
        //solve_king ();
        //solve_knight ();
        //solve_rook ();
        //solve_queen ();  //WA TAT
    }
    
    int main() {
        //init ();
        int T;
        scanf ("%d", &T);
        while (T--) {
            scanf ("%d%d%d", &tp, &n, &m);
            if (tp == 1) {
                printf ("%c
    ", solve_king ());
            } else if (tp == 2) {
                printf ("%c
    ", solve_rook ());
            } else if (tp == 3) {
                printf ("%c
    ", solve_knight ());
                //printf ("%c
    ", dp[tp][n][m]);
            } else {
                printf ("%c
    ", solve_queen ());
            }
        }
        return 0;
    }
    
    
    /*
    void solve_rook() {
        memset (win, 0, sizeof (win));
        win[n][m] = 0;
        for (int i=n; i>=1; --i) {
            for (int j=m; j>=1; --j) {
                if (i == n && j == m) continue;
                win[i][j] = 0;
                if (j < m) {
                    row[i][j] = row[i][j+1];
                    if (row[i][j+1] != m - j) win[i][j] = 1;
                }
                if (i < n) {
                    col[j][i] = col[j][i+1];
                    if (col[j][i+1] != n - i) win[i][j] = 1;
                }
    
                if (win[i][j]) row[i][j]++, col[j][i]++;
    
                int nn = W - i + 1, mm = W - j + 1;
                dp[2][nn][mm] = win[i][j] ? 'B' : 'G';
            }
        }
    }
    */
    /*
    void solve_king() {
        for (int i=n; i>=1; --i) {
            for (int j=m; j>=1; --j) {
                if (i == n && j == m) continue;
                if (j < m) {
                    if (!win[i][j+1]) win[i][j] = 1;
                    if (i < n && !win[i+1][j+1]) win[i][j] = 1;
                }
                if (i < n && !win[i+1][j]) win[i][j] = 1;
                int nn = W - i + 1, mm = W - j + 1;
                dp[1][nn][mm] = win[i][j] ? 'B' : 'G';
            }
        }
        debug ();
    }*/
    /*
    void solve_knight() {
        memset (win, 0, sizeof (win));
        for (int i=1; i<=m; ++i) win[n][i] = -1;
        for (int i=1; i<=n; ++i) win[i][m] = -1;
        win[W-1][W-1] = -1;
        win[n][m] = 0;
        for (int i=n; i>=1; --i) {
            for (int j=m; j>=1; --j) {
                if (i == n && j == m) continue;
                if (win[i][j] == -1) continue;
                if (j < m && i < n-1 && !win[i+2][j+1]) win[i][j] = 1;
                if (j < m-1 && i < n && !win[i+1][j+2]) win[i][j] = 1;
                if (!win[i][j]) {
                    if (j < m && i < n-1 && win[i+2][j+1] == -1) win[i][j] = -1;
                    if (j < m-1 && i < n && win[i+1][j+2] == -1) win[i][j] = -1;
                }
                int nn = W - i + 1, mm = W - j + 1;
                dp[3][nn][mm] = win[i][j] == 1 ? 'B' : win[i][j] == 0 ? 'G' : 'D';
            }
        }
        debug ();
    }
    */

    物理 J Rower Bo(CYD)

    题意:

    给定x轴方向的水流速度、一艘船的初速度和在y轴上的起始位置,求船开到原点处的时间,船的方向总是朝向原点;

    思路:

    Alt text

    在x轴方向和朝向原点方向列出方程:

    ;

    .

    积分后得:

    ;

    .

    将上式积分部分带入下式可化解得:,这样就巧妙消去了积分环节,避免了求与t的关系,若按x,y轴方向分解速度,就要求这个积分,比较伤。

    最后特判一下a=0和v1<=v2的情况。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main()
    {
        int a,v1,v2;
        while(scanf("%d %d %d",&a,&v1,&v2)!=EOF)
        {
            if(a==0)
            {
                printf("0.0000000000
    ");
                continue;
            }
            if(v1<=v2)
            {
                printf("Infinity
    ");
                continue;
            }
            double A=a,V1=v1,V2=v2;
            printf("%.10f
    ",V1*A/(V1*V1-V2*V2));
        }
        return 0;
    }

    鸽巢原理 K Teacher Bo(BH)

    题意:

      平面上n个点,要求判断是否存在两对点对(A,B)和(C,D),使得点对的曼哈顿距离相同,点对可存在一个公共点。

    思路:

      看到题目上xi,yi<=M<=100000,有n^2的点对,根据鸽巢原理,如果存在,最多只要判断M次就可以,时间复杂度

    代码:

    #include <bits/stdc++.h>
    
    const int N = 1e5 + 5;
    std::map<int, int> vis;
    
    struct Point {
        int x, y;
    }p[N];
    
    int dis(Point &a, Point &b) {
        return abs (a.x - b.x) + abs (a.y - b.y);
    }
    
    int main() {
        int T;
        scanf ("%d", &T);
        while (T--) {
            int n, m;
            scanf ("%d%d", &n, &m);
            bool flag = false;
            vis.clear ();
            for (int i=1; i<=n; ++i) {
                scanf ("%d%d", &p[i].x, &p[i].y);
                if (!flag) {
                    for (int j=1; j<i; ++j) {
                        int d = dis (p[j], p[i]);
                        if (vis.count (d) == 0) {
                            vis[d] = 1;
                        } else {
                            flag = true;
                            break;
                        }
                    }
                }
            }
            puts (flag ? "YES" : "NO");
        }
        return 0;
    }
    

      

  • 相关阅读:
    linux 换源
    Jedis使用
    mysql 安装
    ORACLE 11g安装
    网易有道云笔记去除左下角广告
    No module named 'urllib2'
    python+Eclipse+pydev环境搭建
    python-正则表达式基础
    [转]SpringMVC Controller介绍及常用注解
    【Android自学日记】搭建Android开发环境
  • 原文地址:https://www.cnblogs.com/NEVERSTOPAC/p/5708727.html
Copyright © 2011-2022 走看看