Codeforces Round #630 (Div. 2) (A-E)

Codeforces Round #630 (Div. 2)

A
切的有点慢…A题居然这么长…
单独处理一下一条缝的情况,此时不能进行任何该垂直方向上的移动。

B
切的更慢了…没有快速察觉到合数…
因为合数所以至少有两个因子,且这个合数不超过1000,那么其中一个因子一定不超过 1000 \sqrt{1000} 1000 ,约等于31.6,而31恰为第11个素数,那么对于所有不超过1000的数一定会要包含前11个素数中的1个,然后记录一下个数和所属情况对应输出即可。

C
容易证明k完全的大回文串的充分必要条件为每段k串均为相同的小回文串,充分性显然,必要性可以采用反证法。之后对k串的每一对对称位(即第i位和第n - 1 - i位)进行考虑,找出所有k串中这两个位置上出现最多的字母,用该字母覆盖这两位上所有的不同的旧字母显然最优。注意特判一下i == n - 1 - k的情况。

D
构造题。
因为bob的算法仅仅考虑了数字最大,而没有考虑位1之间的关系,所以bob的算法一定不会大于答案。题目要求差值为k,为了简便,我们不妨尝试构造bob的答案为0,真答案为k的情况。记k的最高位为wei,如果能够让bob因为一个高位的1而障目,就忽视了更低位的0,那么我们就可以完成目的。可以将[00]置为k | (1 << wei + 1),[01]置为1 << wei + 1, [10][11]置为(1 << wei + 1) - 1,那么bob就会因为高位的1将dp值变为10000…,而忽视了正确的01111…,最后在答案处成为0。我写的时候用33矩阵,更简洁的22矩阵应该也没问题。


补题
E
与其说是补题…不如说是重看一遍题目…
题目要求的是初始值在[L, R]之间,我晚上以为是操作之后也要保持在该区间内(那还咋做qwq)…

如果只有初始值的约束就简单了…容易发现操作只可以对奇数、偶数的个数进行偶数次的变化,只有当整个棋盘的奇偶性全部相同才能同高度。那么,如果

  • nm为奇数: 无论有什么奇偶性的偶数,一定有另一奇偶性的奇数。所以无论怎么选取,偶数个的一类数一定可以通过若干次操作全部成为另一类,因而此时种数即为 ( R − L + 1 ) n m (R - L + 1)^{nm} (RL+1)nm
  • nm为偶数: 只有当奇数偶数均为偶数个时,整个棋盘才可能变换得到奇偶性全部相同的情况。那么由组合数学容易得到计数表达式: ∑ i 为 偶 数 , 0 ≤ i ≤ n m C n m i a i b n m − i \sum_{i为偶数,0≤i≤nm}C_{nm}^ia^ib^{nm-i} i0inmCnmiaibnmi,其中a是区间[L, R]中偶数的个数,b是[L, R]中奇数的个数,a与b都是常数。考虑二项式生成函数 ( a + b ) n m (a + b)^{nm} (a+b)nm ( − a + b ) m n (-a + b)^{mn} (a+b)mn,求和除以2就是所有的偶数二项式单项式之和。

求ab的值费了点劲…而且还是写的很丑…因为在C++中运算/不是真正的底函数,而是向0取整的"底函数"…
虽然无伤大雅但是纯数学表达式如果弄的不优美就很难受…

小坑点
以前写带取模的quick_pow喜欢把qp的返回值设成int,但是如果在代码中qp不是作为一个最终结果而还要进行其他运算时,int与int之间的运算就有可能会爆范围,这里以后要注意!

const int M = 998244353;

ll qp(ll a, ll p){
    ll res = a, ans = 1;
    while(p){
        if(p & 1) ans = ans * res % M;
        res = res * res % M;
        p >>= 1;
    }
    return (ans % M + M) % M;
}

int main(){
//    Fast;
    ll n, m, L, R; scanf("%lld %lld %lld %lld", &n, &m, &L, &R);
    
    n *= m;
    ll a, b;
    if(L & 1){
        if(L == R) a = 0;
        else a = (R - L - 1) / 2 + 1;
    }
    else a = (R - L) / 2 + 1;
    b = R - L + 1 - a;
    
    ll ans;
    if(n % 2 == 0){
        ans = (qp(a + b, n) + qp(-a + b, n)) % M * qp(2, M - 2);
        ans = (ans % M + M) % M;
    }
    else ans = qp(R - L + 1, n);
    
    printf("%lld\n", ans);
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值