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 }