E. Height All the Same


E. Height All the Same


標籤

  • 組合數學
  • 二項式定理

簡明題意

  • 給定n*m的矩陣,每一個a[i][j]代表(i,j)的高度。你可以執行兩種操作:
  • 1.給任意一個a[i][j]加上2.
  • 2.給兩個相鄰的格子都加1.
  • 現在給出n,m,l,r,問你n*m的矩陣,每個格點的初始值是[l,r]中的任意一個,問有多少種初始值,可以使得經過上面的2種操作,所有格點的值相同。

思路

  • 假設每個格點的高度已知,那麼如何判斷是否能通過上面的操作使得全部相等呢?實際上可以從奇偶性的角度考慮。
  • 如果所有格點都是奇數或者都是偶數,那麼很顯然通過操作1即可。接下來考慮既有奇數格點又有偶數格點的情況。
  • 我們想想操作2的作用。顯然是將奇偶性反轉。假如有4個格點是奇數,那麼可以通過操作2將這4個格點全部變成偶數。概括一下,也就是同奇偶性的數有偶數個,那麼可以先通過操作2使得所有數的奇偶性相同,再通過操作1使得所有數相等。
  • 綜上,所有數奇偶性相同可行(直接操作1),奇數有偶數種可行(先操作2再操作1),偶數有偶數種可行。唯一不可行的是:奇數和偶數都是奇數種。
  • 記下來思考如何計算答案。
  • 1.nm是奇數。那麼奇數和偶數總有一種的個數是偶數。所以怎麼填都可行。答案就是:每個點可以填L-R中的任意一個,也就是每個格點可以填(R-L)種數,一共有nm個格點,答案就是(RL)nm(R-L)^{n*m}
  • 2.n*m是偶數。
  • 那麼我們先從n*m個格子中選出偶數個格子,CnmiC_{n*m}^{i}。再把這些格子填成偶數,xix^{i},剩下的格子填奇數:ynmiy^{n*m-i},所以最後答案就是:
    i=0inmCnmixiynmi\sum_{i=0且i爲偶數}^{n*m}C_{n*m}^{i}x^{i}y^{n*m-i}
  • 回憶二項式定理:
    (x+y)n=i=0nCnixiyni(x+y)^n=\sum_{i=0}^n C_{n}^{i}x^iy^{n-i}
  • 因此上式,我們實際求的是,二項式展開後的偶數項。我們可以構造出一個
    (xy)n=i=0nCnixi(y)ni(x-y)^n=\sum_{i=0}^n C_{n}^{i}x^i(-y)^{n-i}
  • 這個式子中,i爲奇數,n-i也是奇數,那麼i爲奇數時,這一項就是負數。所以(x+y)n+(xy)n2\frac{(x+y)^n+(x-y)^n} {2}剛好把奇數項抵消了,求出來就是二項式偶數項的和的兩倍。
  • 所以n*m是偶數時,答案就是(x+y)n+m+(xy)n+m2\frac{(x+y)^{n+m}+(x-y)^{n+m}}{2}

注意事項


總結

  • CnixiyniC_{n}^{i}x_iy^{n-i}要立馬想到二項式定理。
  • 求二項式展開後的奇/偶數項,要想到構造抵消。
  • 模意義下不要提前給指數取模了。
  • 這裏/2用轉換成乘法逆元~~

AC代碼

#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring> 
#include<stack>
#include<map>
#include<queue>
#include<cstdio>	
#include<set>
#include<map>
#include<string>
using namespace std;

const int mod = 998244353;

int ksm(int a, long long b)
{
	int ans = 1, base = a;
	while (b)
	{
		if (b & 1)
			ans = 1ll * ans * base % mod;
		b >>= 1;
		base = 1ll * base * base % mod;
	}
	return ans;
}

void solve()
{
	int n, m, l, r;
	cin >> n >> m >> l >> r;
	int x = r / 2 - (l - 1) / 2;
	int y = r - l + 1 - x;
	if (1ll * n * m & 1) cout << ksm(r - l + 1, 1ll * n * m);
	else cout << (ksm(x + y, 1ll * n * m) + ksm(x - y, 1ll  * n * m)) *1ll * ksm(2, mod - 2) % mod;
	
}
	
int main()
{
	//freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章