题目:传送门
思路:参考于某大佬(非常清晰+友好)。点此跳转
1. 由于“操作2”,我们可以把原矩阵看作一个01矩阵 (所有数取模2,每个ai,j向上+2 直到最大值和最小值的差<=1)
2. “操作1”的本质是对任意两个点进行翻转(奇偶性变换;考虑如何对不相邻的两个点进行翻转,设这两个点为u、v,那么我们可以对u->v的一条路径上进行相邻两个点的翻转,除了u和v外,路径上其余点均翻转两次)
3.如果所有点奇偶性一致,那么可以通过操作1使得所有点一样高。
4.当n*m是奇数时,那么一定存在着偶数个ai,j 是奇数或者偶数,根据2可知,能将偶数个ai,j 全部翻转使之奇偶性改变(使得所有点奇偶性一致),最后通过操作1能够使所有点一样高。所以当n*m是奇数时,每个点可以取[L,R]的任意值,则 ans=(R-L+1)n*m 。
5.当n*m是偶数时,设sum=Σai,j (1<=i<=n,1<=j<=m):
1)若sum是奇数,则 一定为 奇数个ai,j是奇数 ,奇数个ai,j是偶数 的情况,根据2知 ( 奇数%2 != 0 ),不可能通过 "操作1" 使奇偶性一致。
2)若sum是偶数,则 一定为 偶数个ai,j是奇数 ,偶数个ai,j是偶数 的情况,由4知,最后能够使所有点一样高。设[ L , R ]中,有x个偶数,y个奇数,我们在n*m个点中选择 i 个点填偶数(偶数有x种),剩下的点填奇数(y种),则 ans=Σ Cin*m * xi * yn*m-i ( i = 0,2,4,6,8, ... ,n*m ) 。由二项式展开定理可知,ans=(x+y)n*m * (x-y)n*m / 2 【求展开式中的偶数项 a0 、a2、a4、...】。
###二项式定理
1 #include<bits/stdc++.h> 2 #pragma GCC optimize(2) 3 using namespace std; 4 typedef long long LL; 5 typedef pair<int,int> pii; 6 typedef pair<double,double> pdd; 7 const int N=2e3+5; 8 const int inf=0x3f3f3f3f; 9 const LL mod=998244353; 10 const double eps=1e-9; 11 const long double pi=acos(-1.0L); 12 #define ls (i<<1) 13 #define rs (i<<1|1) 14 #define fi first 15 #define se second 16 #define pb push_back 17 #define mk make_pair 18 #define mem(a,b) memset(a,b,sizeof(a)) 19 LL read() 20 { 21 LL x=0,t=1; 22 char ch; 23 while(!isdigit(ch=getchar())) if(ch=='-') t=-1; 24 while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } 25 return x*t; 26 } 27 LL fp(LL x,LL y) 28 { 29 LL res=1; 30 while(y>0) 31 { 32 if(y&1) res=res*x%mod; 33 x*=x; x%=mod; 34 y>>=1; 35 } 36 return res; 37 } 38 int main() 39 { 40 LL n,m,l,r,ans; 41 scanf("%lld%lld%lld%lld",&n,&m,&l,&r); 42 if(n*m%2==1) ans=fp(r-l+1,n*m); 43 else{ 44 LL x,y;//x为[l,r]中偶数的个数,y为奇数; 45 if((r-l)%2==1) x=y=r-l>>1; 46 else if(l&1) x=r-l>>1,y=x+1; 47 else y=r-l>>1,x=y+1; 48 ans=fp(r-l+1,n*m)+fp(x-y,n*m); 49 ans=ans%mod*fp(2LL,mod-2LL)%mod; 50 } 51 printf("%lld ",ans); 52 return 0; 53 }