E. Height All the Same——Codeforces Round #630 (Div. 2)

E. Height All the Same

题目大意

给出nm的方格,每个方格上面可以放置立方体,初始时坐标为(i,j)的方格上有ai,j个立方体,现在有两个操作:

  • 选择相邻的两个方格并在每个方格上面放置一个立方体
  • 选择一个人方格并在这个方格上放置两个立方体

要求在有限次操作内使得每个方格上的立方体数量相等。
现在给出ai,j的取值[L,R],问你有多少种初始数量的方案可以满足上述要求。

解题思路

因为操作可以任意次,所以不需要考虑具体操作次数,并且可以发现我们可以通过操作1做到选择任意两个方格进行加1的操作。
然后就是想到因为最后数量需要一样,每次都是加1或者加2,所以考虑初始状态的奇偶性。假设全是奇数或者全是偶数,则可以通过操作2完成目标。
假设初始时有x个奇数,y个偶数。
因为操作2不会改变整体方格上立方体数量的奇偶性,只有在奇偶性相同的方格上进行操作1,才会改变整体的奇偶性,如:选择两个奇数数量的方格进行操作1,则整体奇数数量会减2,偶数数量会加2,而选择奇偶性不同的方格操作相当于没变(奇偶性不发生该改变)。
并且每次更改都是2,所以初始奇数的数量或者偶数的数量一定要有一个是偶数,这样才可以满足要求。

  • 如果nm是奇数,那么奇数和偶数中一定有一个的数量是偶数,答案直接就是 (RL+1)nm
  • 如果是偶数,则需要计算,利用组合数学得出i=0nmCnmixiy(nmi)[i%2=0]

对于第二种情况,
根据二项式定理可得:(xy)(nm)=i=0nmCnmixiy(nmi)(1)nmi=i=0nmCnmixiy(nmi)(1)i
所以奇数项是1,偶数项是1,我们只要求出偶数项的值即可。
(x+y)nm=i=0nmCnmixiy(nmi)
因此ans=(xy)nm+(x+ynm)2

故:
nm是奇数时,ans=(RL+1)nm
否则ans=(xy)nm+(x+ynm)2  (xy)

Code

#include <bits/stdc++.h>
#define ll long long
#define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
#define V vector
using namespace std;
const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;

inline char nc() {
    static char buf[1000000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}
template <typename _Tp> inline void read(_Tp&sum) {
    char ch = nc(); sum = 0;
    while (!(ch >= '0'&&ch <= '9')) ch = nc();
    while (ch >= '0'&&ch <= '9') sum = (sum << 3) + (sum << 1) + (ch - 48), ch = nc();
}

ll n,m,l,r;

ll ksm(ll x,ll y)
{
    ll p = 1;
    while(y)
    {
        if(y & 1)p = p * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return p;
}

void solve(){
    read(n);
    read(m);
    read(l);
    read(r);
    if((n * m) & 1){
        printf("%lld\n",ksm((r - l + 1), n * m));
    }else{
        ll x = 0, y = 0;
        if((l & 1) && (r & 1)){
            x = (r - l) / 2;
            y = (r - l) / 2 + 1;
        }else if(!(l & 1) && !(r & 1)){
            x = (r - l) / 2 + 1;
            y = (r - l) / 2;
        }else{
            x = y = (r - l + 1) / 2;
        }
        printf("%lld\n",((ksm(abs(x - y), n * m) + ksm(x + y, n * m)) % mod) * ksm(2ll, mod - 2) % mod);
    }
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif

    int T = 1;
    // scanf("%d",&T);
    while(T--){
        solve();
    }
    return 0;
}
posted @   !^^!  阅读(22)  评论(0编辑  收藏  举报
编辑推荐:
· 探秘 MySQL 索引底层原理,解锁数据库优化的关键密码(下)
· 大模型 Token 究竟是啥:图解大模型Token
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
阅读排行:
· 2025,回顾出走的 10 年
· 【保姆级教程】windows 安装 docker 全流程
· 分享 3 款基于 .NET 开源且免费的远程桌面工具
· 基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程
· 由 MCP 官方推出的 C# SDK,使 .NET 应用程序、服务和库能够快速实现与 MCP 客户端
点击右上角即可分享
微信分享提示