• Experimental Educational Round: VolBIT Formulas Blitz


    题目链接:https://codeforces.com/contest/630

    A - Again Twenty Five!

    C - Lucky Numbers

    B - Moore's Law

    D - Hexagons!

    J - Divisibility

    注意[2,10]的lcm是 (2^3*3^2*5*7) ,也就是每种质因子取最高次。为2520。

    F - Selection of Personnel

    这个组合数 (C_{777}^7) 刚好不会溢出ll,一种防溢出的组合数的写法,先处理出分母这个比较小的,然后对于分子的每个部分都先和分母约分再乘上去,这样保证中间的结果都不会超过答案的 (C_{777}^7)

    ll C(int n, int m) {
        ll up = 1, down = 1;
        for(int i = 1; i <= m; ++i)
            down *= i;
        for(int i = 1; i <= m; ++i) {
            ll tmp = (n + 1 - i);
            ll g = __gcd(tmp, down);
            tmp /= g;
            down /= g;
            up *= tmp;
        }
        return up / down;
    }
    

    R - Game

    题意:有一个 (n*n) 的空白棋盘,两个玩家轮流涂黑格子,每次可以选一个与已经涂黑的格子没有公共边的格子图。无法操作的人输。求谁赢。

    题解:这种题目有一个“模仿对手”的策略,易知若 (n) 为偶数,那么每次先手选择之后,后手选择对应的中心对称的位置,必然是可以的,所以最后一定会是先手输;若 (n) 为奇数,一开始先手先把正中间占了,然后又变成了可以跟着后手选中心对称的位置,最后一定是后手输。

    N - Forecast

    题意:求一个二次方程的两个不同的实根,保证有两个不同的实根,先输出大的,再输出小的。

    题解:由于a的符号可能是负的,所以未必一定有 (x_1=frac{-b+sqrt{b^2-4ac}}{2a}>x_2=frac{-b-sqrt{b^2-4ac}}{2a}) ,需要判断然后交换。

    K - Indivisibility

    题意:求[1,n]内有多少个数,不被[2,10]其中任意一个数整除。

    题解:易知不被[2,3,5,7]整除就是不被[2,10]的任意一个数整除,那么就是容斥原理,乘个莫比乌斯函数就可以了,注意不要漏了。

    void TestCase() {
        ll n;
        scanf("%lld", &n);
        ll ans = n;
        ans -= n / 2;
        ans -= n / 3;
        ans -= n / 5;
        ans -= n / 7;
        ans += n / 6;
        ans += n / 10;
        ans += n / 14;
        ans += n / 15;
        ans += n / 21;
        ans += n / 35;
        ans -= n / 30;
        ans -= n / 42;
        ans -= n / 70;
        ans -= n / 105;
        ans += n / 210;
        printf("%lld
    ", ans);
    }
    

    那么这个式子看起来像什么呢?反正不是正常的莫比乌斯函数求和,求解的复杂度应该就是 2^k ,k是参与容斥的质数的个数。

    H - Benches

    题意:在一个 (n*n) 的棋盘上面放5个相同的棋子,要求同一行和同一列至多有一个棋子,问有多少种放法。

    题解:第一次放,有 (n*n) 种放法,然后去掉这一行一列,第二次放有 ((n-1)*(n-1)) 种放法……注意最后棋子是无序的,把这个全排列除掉。

    小心溢出,经过严密的计算,最终结果应该就是1e18的级别,是不会溢出的,也要像上面那样分次约分。

    void TestCase() {
        ll n;
        scanf("%lld", &n);
        ll m = 120;
        ll res1 = n * n * (n - 1) * (n - 1) * (n - 2) * (n - 2);
        ll g = __gcd(res1, m);
        res1 /= g;
        m /= g;
        ll res2 = (n - 3) * (n - 3) * (n - 4) * (n - 4);
        g = __gcd(res2, m);
        res2 /= g;
        m /= g;
        printf("%lld
    ", res1 * res2 / m);
    }
    

    L - Cracking the Code

    要注意的是,需要输出前导零。

    G - Challenge Pennants

    题意:有n个不同的盒子,5个相同的红球,3个相同的蓝球,每个球都要放在一个盒子里,一个盒子可以放任意个球。求多少种方法。

    题解:首先把红蓝球分步,然后把5个红球的分法分类:

    5、4+1、3+2、3+1+1、2+2+1、2+1+1+1、1+1+1+1+1

    这些用组合数很好算。

    ll C(ll n, ll m) {
        if(n < m)
            return 0;
        ll up = 1, down = 1;
        for(int i = 1; i <= m; ++i) {
            up *= (n + 1 - i);
            down *= i;
        }
        return up / down;
    }
     
    void TestCase() {
        int n;
        scanf("%d", &n);
        ll res1 = 0;
        res1 += C(n, 1);
        res1 += C(n, 1) * C(n - 1, 1);
        res1 += C(n, 1) * C(n - 1, 1);
        res1 += C(n, 1) * C(n - 1, 2);
        res1 += C(n, 2) * C(n - 2, 1);
        res1 += C(n, 1) * C(n - 1, 3);
        res1 += C(n, 5);
        ll res2 = 0;
        res2 += C(n, 1);
        res2 += C(n, 1) * C(n - 1, 1);
        res2 += C(n, 3);
        printf("%lld
    ", res1 * res2);
    }
    

    I - Parking Lot

    和昨晚(2020/3/23)的Edu一样。

    E - A rectangle

    题意:给出一个矩形的左下角和右上角的坐标,求把这个矩形涂黑需要涂黑多少个六边形?

    按这个图理解,应该是分奇偶性讨论一下。但是WA22了,是这个图有误导性。

    void TestCase() {
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        if((x1 - x2) % 2 == 0) {
            //有奇数列
            if((x1 - y1) % 2 == 0) {
                //左下角在中心
                if((x2 - y2) % 2 == 0) {
                    //右上角也在中心
                    ll dy = abs(y2 - y1) / 2;
                    //少的列是dy
                    ll dx = abs(x2 - x1) + 1;
                    //有奇数列
                    ll sum = (dx - 1) / 2 * dy + (dx + 1) / 2 * (dy + 1);
                    printf("%lld
    ", sum);
                    return;
                } else {
                    //右上角在边界
                    ll dy = abs(y2 - y1) / 2 + 1;
                    //每列都是dy
                    ll dx = abs(x2 - x1) + 1;
                    //有奇数列
                    ll sum = dx * dy;
                    printf("%lld
    ", sum);
                    return;
                }
            } else {
                //左下角在边界
                if((x2 - y2) % 2 == 0) {
                    //右上角在中心
                    ll dy = abs(y2 - y1) / 2 + 1;
                    //每列都是dy
                    ll dx = abs(x2 - x1) + 1;
                    //有奇数列
                    ll sum = dx * dy;
                    printf("%lld
    ", sum);
                    return;
                } else {
                    //右上角也在边界
                    ll dy = abs(y2 - y1) / 2;
                    //少的列是dy
                    ll dx = abs(x2 - x1) + 1;
                    //有奇数列
                    ll sum = (dx - 1) / 2 * (dy + 1) + (dx + 1) / 2 * dy;
                    printf("%lld
    ", sum);
                    return;
                }
    
            }
        } else {
            //有偶数列
            if((x1 - y1) % 2 == 0) {
                //左下角在中心
                if((x2 - y2) % 2 == 0) {
                    //右上角也在中心
                    ll dy = abs(y2 - y1) / 2 + 1;
                    //每列都是dy
                    ll dx = abs(x2 - x1) + 1;
                    //有偶数列
                    ll sum = dx * dy;
                    printf("%lld
    ", sum);
                    return;
                } else {
                    //右上角在边界
                    ll dy = abs(y2 - y1) / 2;
                    //少的列是dy
                    ll dx = abs(x2 - x1) + 1;
                    //有偶数列
                    ll sum = dx / 2 * dy + dx / 2 * (dy + 1);
                    printf("%lld
    ", sum);
                    return;
                }
            } else {
                //左下角在边界
                if((x2 - y2) % 2 == 0) {
                    //右上角在中心
                    ll dy = abs(y2 - y1) / 2;
                    //少的列是dy
                    ll dx = abs(x2 - x1) + 1;
                    //有偶数列
                    ll sum = dx / 2 * dy + dx / 2 * (dy + 1);
                    printf("%lld
    ", sum);
                    return;
                } else {
                    //右上角也在边界
                    ll dy = abs(y2 - y1) / 2 + 1;
                    //每列都是dy
                    ll dx = abs(x2 - x1) + 1;
                    //有偶数列
                    ll sum = dx * dy;
                    printf("%lld
    ", sum);
                    return;
                }
            }
        }
    }
    

    原来CF也有错题的,不过有人喷过了。这道题还限制了输入只有奇数列的情况。对于输入1 0 5 6,按照上图来理解应该是17个(3+4+3+4+3),但是答案却是18个(4+3+4+3+4),我表示强烈谴责。

    void TestCase() {
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        ll dy = abs(y2 - y1) / 2;
        ll dx = abs(x2 - x1) + 1;
        ll sum = (dx - 1) / 2 * dy + (dx + 1) / 2 * (dy + 1);
        printf("%lld
    ", sum);
    }
    

    M - Turn

    题意:要求将一张照片顺时针旋转d度。分两个步骤:顺时针旋转x次90度;顺时针或逆时针旋转nd度。要求在nd最小的前提下,最小化x。

    题解:易知直接把d模360到[0,359],然后枚举旋转0次、1次、2次、3次的度数(0,90,180,270)算出与d的夹角的值,找到最小的那个输出。注意是夹角,所以并非是两者作差这么简单,比如要把0度理解为0度或者360度。或者说,算出两个[0,359]的角的差的绝对值abs之后,还要取min(abs,360-abs)才是夹角。

    void TestCase() {
        ll d;
        scanf("%lld", &d);
        d %= 360;
        if(d < 0)
            d += 360;
        int ans = INF, cnt = 0;
        for(int i = 0; i < 4; ++i) {
            int nd = abs(d - 90 * i);
            if(min(nd, 360 - nd) < ans) {
                ans = min(nd, 360 - nd);
                cnt = i;
            }
        }
        printf("%d
    ", cnt);
    }
    

    Q - Pyramids

    题意:给出所有边都相等的正三棱锥、正四棱锥、正五棱锥的棱长,求体积。

    题解:由底面的正n边形的棱长可以算出正n边形对应的外接圆的半径。方法是:从底面圆心向各个顶点连线,划分成若干个全等的等腰三角形,可以轻松计算出等腰三角形的底角的大小(通过顶角是圆心角,或者内角和公式 (pi(n-2)) 都可以算出来),然后用棱长的一半,除以这个底角的cos值,就得到了底面外接圆的半径。得到了底面外接圆的半径,联系棱长,就可以求出这个棱锥的高(勾股定理)。最后要求底面正多边形的面积,这个可以直接计算出圆心角,然后用三角形面积公式 (frac{1}{2}sin alpha r^2) 算出每个等腰三角形的面积。最后体积要记得除以3。也就是 (V_{锥}=frac{1}{3}S_{底}h)

    const double PI = acos(-1.0);
    
    double calc_r(double l, int n) {
        double s = PI * (n - 2);
        double d = (s / n) / 2.0;
        return (l / 2.0) / cos(d);
    }
    
    double calc_s(double r, int n) {
        double s = 0.5 * sin(2.0 * PI / n) * r * r;
        return s * n;
    }
    
    void TestCase() {
        double l3, l4, l5;
        scanf("%lf%lf%lf", &l3, &l4, &l5);
    
        double r3 = calc_r(l3, 3);
        double h3 = sqrt(l3 * l3 - r3 * r3);
        double s3 = calc_s(r3, 3);
    
        double r4 = calc_r(l4, 4);
        double h4 = sqrt(l4 * l4 - r4 * r4);
        double s4 = calc_s(r4, 4);
    
        double r5 = calc_r(l5, 5);
        double h5 = sqrt(l5 * l5 - r5 * r5);
        double s5 = calc_s(r5, 5);
    
        printf("%.12f
    ", (s3 * h3 + s4 * h4 + s5 * h5) / 3.0);
    }
    
  • 相关阅读:
    Php7安装pdo_pgsql,pgsql扩展
    Laravel 实时监听打印 SQL
    windows 下安装docker依赖boot2docker镜像默认用户和密码
    win7下安装virtual box后启动报错
    phpstorm 不能自动打开上次的历史文件
    BZOJ1001 [BeiJing2006]狼抓兔子 平面图转对偶图,最小割转最短路
    BZOJ1098 [POI2007]办公楼biu
    POJ1410 Intersection
    HDU3336 Count the string
    HDU2594 Simpsons’ Hidden Talents [KMP]
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12558009.html
Copyright © 2020-2023  润新知