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;
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12696212.html