CF1332E Height All the Same(数学)
这道题是一道思维+组合计数的题目
题目给了两个操作,我们发现第一个操作并不改变奇偶,但是可以把相同奇偶的数变成同一个数,第二个数可以改变相邻数的奇偶性
这样就是一个经典问题了,问每次改变相邻两个数的奇偶性,能不能将所有的数变成奇偶性相同的。
答案就是,只要在这个区域内,奇数和偶数的个数不都为奇数就行。因为这样我们就可以把个数是奇数的,如果两类都是偶数,随便移一类就行
通过交换奇偶的方式,全部移到边上靠着
1 1 1 1
2 2 2 2
2 2 2 2
例如这样,因为其中一类数都移到边上了,所以剩下的一类数,不但是偶数个,还相邻,这样就可以通过两个两个改变,将所有的数的奇偶性都变成一样。
这里也就发现如果都是奇数,那是不行的,因为没法配对。
之后就是一个组合计数问题,如果棋盘是奇数个,那么全部状态都是可以的。如果棋盘是偶数个,我们就可以推出公式,保证在取得时候是偶数个得时候取,因为奇数+奇数=偶数,这种是不行的
这个公式的物理意义就是在n*m中选i个位置给奇数,那么每个位置有x(l-r中的奇数个数)种选择,其他位置有y种选择(l-r中的偶数个数)
本题要用快速幂求,还要求逆元,因为根据公式构造得二项式为((x+y)^n*m+(x-y)^n*m)/2;
因为要取模,所以2要变成逆元
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<map> #include<string> #include<vector> using namespace std; typedef long long ll; const int N=2e5+5; const ll mod=998244353; ll qpow(ll m,ll k){ ll res=1%mod; ll t=m%mod; while(k){ if(k&1){ res=res*t%mod; } t=t*t%mod; k>>=1; } return res%mod; } int main(){ ll n,m; ll l, r; ll ans=0; cin>>n>>m>>l>>r; if(n*m&1){ ans=qpow(r-l+1,m*n); cout<<ans<<endl; } else{ ans=qpow(r-l+1,m*n)+((r-l+1)&1?1:0); ans%=mod; ans=(ans*qpow(2,mod-2)); ans%=mod; cout<<ans<<endl; } return 0; }
没有人不辛苦,只有人不喊疼