zoukankan      html  css  js  c++  java
  • [补]2019nowcoder牛客第五场G、I

    ---恢复内容开始---

    红小豆少见的及时更新系列

    I  three points 1

      当大家在枚举少量情况并检验试图找到一个答案的时候,我总是在所有情况里试图构造一个正确的答案

      于是大家AK了我也没AC,完。

      一个三角形在矩形里放置,并考虑点和边的顺序,有效的情况一共就六种,就算加上“广义三角形”-----直线也是ok的。当固定一个点在原点时,另一个在矩形的边上的点有两种情况,如下图,根据这两点的坐标和此时可知的夹角可以得到第三点的坐标,对其进行边界检查,符合即可输出。因为默认把矩形最长边放在下方,所以根据是否有旋转矩形,还要把点的坐标旋转回去。

      考虑到精度问题没有用acos什么的,所以还要根据情况特判某个角的cos,(场上就各种-nan来着)_(:з」∠)_

      场上写的未AC码已经不想看了,重写了一份补题码自我感觉良好

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    #define CR(t,x) const t&x
    #define CRP(x) CR(point,x)
    #define double long double
    const double eps = 1e-12;
    double w, h, a[5];
    int t;
    struct point
    {
        double x, y;
        void chg() { swap(x, y); }
    }p[5];
    double dis(CR(point, l), CR(point, r)) {
        return (l.y - r.y) * (l.y - r.y) + (l.x - r.x) * (l.x - r.x);
    }
    
    int che(int d, int l, int r, int x, int y, int z,bool c)
    {
        p[y].y = (a[d] > w) ? (sqrt(a[d] * a[d] - w * w)) : 0;
        p[y].x = p[y].y ? w : a[d];
        double cB = (a[d] * a[d] + a[l] * a[l] - a[r] * a[r]) / (2 * a[d] * a[l]);
        double sB = sqrt(1 - cB * cB);
        double cP = p[y].y ? ((a[d] * a[d] + w * w - p[y].y * p[y].y) / (2 * a[d] * w)) : 1;
        double sP = sqrt(1 - cP * cP);
        double cQ = cB * cP - sB * sP;
        double sQ = sqrt(1 - cQ * cQ);
        p[x].x = p[x].y = 0;
        p[z].x = a[l] * cQ; p[z].y = a[l] * sQ;
        if (p[z].x + eps >= 0 && p[z].x - eps <= w && p[z].y + eps >= 0 && p[z].y - eps <= h ) {
            if (c) { p[x].chg(); p[y].chg(); p[z].chg(); }
            printf("%.12Lf %.12Lf %.12Lf %.12Lf %.12Lf %.12Lf
    ", p[1].x, p[1].y, p[2].x, p[2].y, p[3].x, p[3].y);
            return 1;
        }
        return 0;
    }
    
    
    int main()
    {
        scanf("%d", &t);
        while (t--) {
            double ma; bool fg = 0;
            scanf("%Lf%Lf%Lf%Lf%Lf", &w, &h, &a[1], &a[2], &a[3]);
            ma = max(a[1], max(a[2], a[3]));
            if (h > w)swap(w, h), fg = 1;
            if (che(1, 2, 3, 1, 2, 3,fg));
            else if (che(1, 3, 2, 2, 1, 3,fg));
            else if (che(2, 1, 3, 1, 3, 2,fg));
            else if (che(2, 3, 1, 3, 1, 2,fg));
            else if (che(3, 2, 1, 3, 2, 1,fg));
            else che(3, 1, 2, 2, 3, 1,fg);
    
        }
        return 0;
    }
    three points 1

    ---恢复内容结束---

    有上面这个东西是因为吃了个饭电脑好像自己重启了_(:з」∠)_

    G  subsequence 1

      应该和020互换题目做的)

      这是一道基础dp,出题人如是说。用到了组合数学,补充。

      第一维表示s串位置,第二维表示t串位置,存当前方案数:

        首先当前方案数以i-1位与j位匹配的方案数为基础;

        如果这一位上s比t大,那么  后面n-i位里随便选m-j个的方案数(选了这位之后,后面就可以随便选)  乘上  两个串匹配到上一位的时候的方案数(组合嘛)  就是选择加入这一位提供的答案贡献(直接加进ans里);

        如果这一位s和t相等,那么该位的方案数就再加上[i-1][j-1]的时候的方案数,即选ta或者不选ta

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const LL mod = 998244353;
    int t, n, m;
    char s1[3005], s2[3005];
    LL ans;
    LL c[3005][3005],d[3005][3005];
    
    void C()
    {
        c[0][0] = 1;
        for(int i=1;i<=3000;i++){
            c[i][0] = 1;
            for (int j = 1; j <= 3000; j++)
                c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
        }
    }
    
    int main()
    {
        scanf("%d", &t);
        C();
        while (t--) {
            scanf("%d%d", &n, &m);
            scanf("%s %s", s1+1, s2+1);
            ans = 0;
            for (int i = 1; i <= n; i++){
                if (s1[i] == '0')continue;
                for (int j = m; j <= n - i; j++)
                    ans = (ans + c[n-i][j]) % mod;
            }
            for (int i = 0; i <= n; i++)d[i][0] = 1;
            for(int i=1;i<=n;i++)
                for (int j = 1; j <=min(m,i); j++) {
                    d[i][j] = d[i-1][j];
                    if (s1[i] > s2[j])ans = (ans + d[i-1][j-1] * c[n - i][m - j] % mod) % mod;
                    if (s1[i] == s2[j])d[i][j] = (d[i][j] + d[i - 1][j - 1]) % mod;
                }
            cout << ans << endl;
        }
    
        return 0;
    }
    subsequence 1

      其实[0][0]应该是0的,因为两个空集不会larger than。但是如果第一位就大于的话,就要用到[0][0]来乘组合数,如果ta等于0就会失去一部分方案┓( ´∀` )┏

      以上!

  • 相关阅读:
    SQL SERVER CXPACKET-Parallelism Wait Type 的惯用解决方案
    服务器主体 "sa" 无法在当前安全上下文下访问数据库 XXX[SQLSTATE 08004] (错误 916). 该步骤失败。
    Android 使用 aapt 命令查看 apk 包名
    Android数据库GreenDao的使用总结
    NestedScrollView、ScrollView 加载完自动滑动至底部问题的解决方案
    Android框架式编程之Retrofit
    Visual Studio 开发(三):Visual Studio 使用时常见问题解决方案
    Android 网络交互之移动端与服务端的加密处理
    Android框架式编程之ViewModel
    Android框架式编程之LiveData
  • 原文地址:https://www.cnblogs.com/non-/p/11291228.html
Copyright © 2011-2022 走看看