• Codeforces Round #630 (Div. 2)


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

    A - Exercising Walk

    贪心一下。

    B - Composite Coloring

    题意:给若干个1000以内的合数,把他们染成若干种颜色,使得两个相同颜色的数字的gcd都不为1。输出答案时,要求输出使用的颜色数m,且恰好用[1,m]中每种颜色至少1次。

    题解:1000以内的合数的质因数恰好有11种,每种质数就把其倍数全部染色,最后把颜色离散化到[1,m]。

    C - K-Complete Word

    题意:给一个长度为n的字符串,和n的一个因数k。定义一个字符串是“k完全的”,当其由长度为k的n/k个完全相同的回文串拼接形成(也就是说周期也是k)。修改一个字符的消耗是1,求最小的消耗使得这个字符串变为“k完全的”。

    题解:某些对应位置的字符是要求完全相同的,包括回文和周期两方面的影响,把这些位置的字符数量统计出来,然后保留最多的一种,其他的往最多的变。贪心。

    D - Walk on Matrix

    题意:假如有一个n*m的数字矩阵,那么要求从左上角(1,1)走到右下角(n,m),每次只能往右走或者往下走,把路径上的数字全部“按位与”就得到一个结果。求所有路径中的结果的最大值,记为A。有个逗B弄了一个假算法,假算法是这样的:

    把假算法的结果记为B。

    给一个数字k<=1e5,构造一个不超过500*500的矩阵,矩阵中的元素不超过3e5,使得A和B的差值恰好为k。

    题解:首先要观察这个假算法假在哪里:假在max运算有可能会保留高位而抛弃低位,而高位最后会因为“按位与”而不能保留,恰好低位可以暴力,就会出错。那么正确的算法很简单:贪心,从高位开始逐位验证该位是否存在一条全1的路径使得该位可以保留1,若可以,则该位必定是1,且后续选择的路径必须在这些全1路径中选。换言之,就是先取第1位,看看是否有一条全1的路,若有,则验证是否有第1位和第2位都是1的路,若还有,则验证是否有第1位和第2位和第3位都是1的路,直到某位不可以是1,那么这位必须是0,复杂度是O(nmlog)。

    回到这个题目,显然A>=B,不妨设A=B+k,按常理一般看看是否可以使得B=0,这时A最大要到k,也挺符合构造的。根据上面的观察,推测是否可以构造一个最高位来欺骗假算法走错,恰好可以构造p17=(1<<17)这个数,这个数首先与[1,1e5]的二进制位都没有冲突,加上k也不超过3e5。

    构造了很久,最后发现:

    |  p17+k  |    k    |   p17   |
    |   p17   |  p17+k  |    k    |
    

    这个矩阵会诱导假算法保留p17。

    E - Height All the Same

    题意:假设有一个n*m的平面矩阵,上面每个格子有一些方块,有两种操作,第1种操作是给连续的两个格子都放1个方块,第2种操作是给同一个格子放2个方块,给出这个平面矩阵的初始状态,问是否可以把这个平面矩阵变得一样高。(上次想要的那个A题来了)

    对所有的n*m的平面矩阵,每个元素都在[L,R]自由取值,统计可以变得一样高的平面矩阵的数目。

    题解:

    1. 推论:由于第2种操作的存在,可以把值全部模2。

    证明:记最大值为M,那么其他值都可以通过第2种操作加到M-1或者M。

    问题变成:给一个n*m的平面矩阵,元素都是0或者1,第1种操作变为给连续的两个格子同时翻转,求是否可以把整个矩阵变成全0或者全1。

    1. 推论:可以同时翻转任意两个格子,不需要连续。

    证明:选择想要翻转的两个格子,然后连接他们有一条路,对路上的格子依次进行第1种操作,最后只有首尾的格子受到影响,中间的格子恰好都经过两次第1种操作抵消了。

    问题变成:给一个n*m的平面矩阵,元素都是0或者1,操作是给任意两个格子同时翻转,求是否可以把整个矩阵变成全0或者全1。

    1. 推论:n*m为奇数个格子必定有解。

    证明:由推论2可以知道,可以无限制给元素总和+2或者-2,不改变其奇偶性,总是可以变成全0或者全1。

    1. 推论:n*m为偶数个格子,若元素总和为偶数必定有解,若元素总和为奇数必定无解。

    证明:同上

    1. 推论:区间[L,R]可以平移为区间[0,R-L],为方便可以记k=R-L。

    证明:n*m为偶数个格子的时候,可以经过铺一层第1种操作强行把每个格子的奇偶性翻转,所以可以偶数个格子的情况可以对取值区间进行平移。

    题解:那么给n*m的值分类讨论,假如是奇数那么直接快速幂。否则前n*m-1个格子可以任选,最后一个格子要视情况补回奇偶性。

    统计这个东西的时候却不会统计,看官方题解:


    Let's find out the number of ways to choose the grid such that the number of even cells is even and (0 le a_i le k).


    Suppose that there are (E) even numbers in ([0,k]), (O) odds. Therefore, for any given (0 le i le nm), the number of ways to have exactly (i) even numbers should be (E^i O^{nm-i} imes inom{nm}{i}). Thus, the total answer should be (sum limits_{i=0}^{nm/2} E^{2i} O^{nm-2i} inom{nm}{2i}), which should remind you of the Newton expansion.


    Note that


    ((E+O)^{nm}=sum_{i=0}^{nm/2}E^{2i}O^{nm-2i}inom{nm}{2i}+sum_{i=1}^{nm/2}E^{2i-1} O^{nm-(2i-1)} inom{nm}{2i-1})


    and


    ((E-O)^{nm}=sum_{i=0}^{nm/2}E^{2i}O^{nm-2i}inom{nm}{2i}-sum_{i=1}^{nm/2}E^{2i-1} O^{nm-(2i-1)} inom{nm}{2i-1})
    .


    Adding those two formulas will get us exactly the formula we were looking for but doubled. Thus, the answer is that divided by (2).

    这个什么东西来的啊。(其实是二项式定理)

    启发:类似这种 (C_{n}^{i}a^{i}b^{n-i}) 形式的求和,假如i是只取奇数或者只取偶数,可以巧妙构造二项式定理来求解。

    const ll MOD = 998244353ll;
    
    ll qpow(ll x, ll n) {
        //这里并不需要操作指数,就算操作指数也最好使用扩展欧拉定理
        //扩展欧拉定理可以避免0^0也返回1的情况,会正确返回0
        //n = n % (MOD - 1ll) + (MOD - 1ll);
        ll res = 1ll;
        while(n) {
            if(n & (1ll))
                res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }
    
    void TestCase() {
        ll n, m, L, R;
        scanf("%lld%lld%lld%lld", &n, &m, &L, &R);
        if(n * m % 2 == 1) {
            ll ans = qpow(R - L + 1ll, n * m);
            printf("%lld
    ", ans);
            return;
        } else {
            ll O = (R - L + 1ll) / 2ll;
            ll E = (R - L + 1ll) - O;
            ll tmp1 = qpow(O + E, n * m);
            ll tmp2 = qpow(O - E, n * m);
            ll ans = (tmp1 + tmp2) * qpow(2ll, MOD - 2ll) % MOD;
            printf("%lld
    ", ans);
            return;
        }
    }
    

    提示:通常写的快速幂算法要求指数不为0,这样会使得res至少叠加上一次x从而返回正确的结果,而一般情况下若指数为0,底数不为0,结果也是正确的1。

    也就是说,快速幂算法在指数为0的情况出现某种特例:没有给res一开始就取MOD,有可能导致溢出。
    在底数为0,且指数也为0的情况,会出现另一种特例:没有给res叠加一个0,导致返回1。

    问题在于0的正整数次幂应该为0,这时快速幂算法可能会出错,意思是快速幂的时候最好特判一下底数的情况。尤其小心在使用欧拉定理之后可能导致指数为0的情况,假如不管发生什么都强行把指数+PHIMOD(扩展欧拉定理)就可以避免指数过小的情况。

  • 相关阅读:
    PHP数字补零的两种方法
    php 防跨站表单提交
    PHP字符串压缩
    原生JS实现表单序列化serialize()
    java并发实现原子操作
    Effective java -- 9 并发/序列化
    Effective java -- 8 异常
    Effective java -- 7 通用程序设计
    Effective java -- 6 方法
    Effective java -- 5 枚举和注解
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12634608.html
Copyright © 2020-2023  润新知