Codeforces Round #630 (Div. 2) E. Height All the Same(组合数学 快速幂 逆元)

https://codeforces.com/contest/1332/problem/E

题面说了一大堆,直接可以抽象为一个n*m的矩阵,每一个a[i][j]代表网格(i,j)的高度。你可以执行两种操作:
1.给任意一个a[i][j]加上2.
2.给两个相邻的格子都加1.
现在给出n,m,l,r,问你n*m的矩阵,每个格点的初始值是[l,r]中的任意一个,问有多少种初始值,可以使得经过上面的2种操作,所有格点的值相同。

如何判断上述操作能否使得所有矩阵的权值相等?从初始矩阵大小和权值的奇偶性考虑。

1、若n*m为奇数,此时必定有偶数个 (权值为奇数的单元或偶数个权值为偶数的单元),必定可以通过上述操作构造出权值同奇偶的情况。这种情况的总方案数是(R-L+1)m*n 这一部分直接用快速幂处理即可。

2、难点就在于n*m为偶数的情况。假设a为初始时,矩阵单元权值为奇数的个数,b为权值是偶数的个数。如果a是奇数,无论怎么用上述操作,都无法使得所有的a与b同奇偶。

只有当a和b都为偶数时,才可以变为同奇偶。

 1 #include<cstring>
 2 #include<iostream>
 3 #include<cstdio>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn = 265000;
 7 const ll mod = 998244353;
 8 ll q_pow(ll x,ll n){
 9     ll res = 1;
10     while(n){
11         if(n&1) res = (res * x)%mod;
12         x = x*x%mod;
13         n>>=1;
14     }
15     return res;
16 }
17 int main() {
18     ll n,m,l,r;
19     cin>>n>>m>>l>>r;
20     ll ans;
21     if(ll(n*m)%2){
22         ans = q_pow(r-l+1,n*m);
23     }
24     else{
25         ll cnt = r - l + 1;
26         ll inv2 = q_pow(2,mod-2);
27         ans = ( q_pow(cnt,m*n) + q_pow(cnt&1?1:0,m*n) )%mod;
28         ans = ans*inv2%mod;
29     }
30     cout<<ans;
31     return 0;
32 }
原文地址:https://www.cnblogs.com/AaronChang/p/12657376.html