CodeForces 1332E

题意:

有两种操作如下,问有多少种初始状态最终可以通过这两种方式达到最终要求。
数据范围:(1≤n,m,L,R≤10^9, L≤R, n⋅m≥2)
答案模 (998,244,353)
操作1和2

分析:

1.每个方格中立方体的数量不重要,重要的是数量的奇偶性。

  因为操作 (2) 可以把相同奇偶性的方格中的立方体数量变为一致,不同奇偶性的也可以变为相同的奇偶性。

2.可以在同时改变两个方格 (u,v) 数量的奇偶性,不管是否是相邻。

  因为,两个方格之间必然存在一条路径:(w_0w_1w_2...w_n),其中 (w_0=u,w_n=v)。对该条路径进行操作 (1),就可以保证除路径的起点和端点数量增加 (1),奇偶性改变外,路径上其余点的数量都增加 (2),奇偶性不变。

3.当 (n imes m) 为奇数时,无论初始状态如何,最终都可以转换为目标状态。

  因为一个奇数必然等于一个奇数加上一个偶数,所以必然存在 偶数个方格数量为奇数个 或者 偶数个方格数量为偶数,这两种情况中的一种。根据 (2) 的结论,可以改变着偶数个方格的奇偶性,再利用操作 (2),就可以达到目的。

4.当 (n imes m) 为偶数,并且 (sum_{i=1}^{n}{sum_{j=1}^{m}{a_{i,j}}}) 为偶数时,无论初态如何,最终都可以转化为目标状态。

  因为偶数等于两个奇数或者两个偶数之和,如果数量为偶数和数量为奇数的方格数均为偶数,分析和 (3) 相同。而且不存在二者均为奇数的情况,否则 (sum) 就不满足条件。

5.当 (n imes m) 为偶数,并且 (sum_{i=1}^{n}{sum_{j=1}^{m}{a_{i,j}}}) 为奇数时,无论初态如何,采用怎样的策略,最终都不可能转化为目标状态。

实现:

(n imes m) 为奇数时,(ans=(R-L+1)^{nm} \%mod)
(n imes m) 为偶数时,
([L,R]) 内的奇数个数为:(x),偶数个数为 (y)
那么

[ans=sum_{i=0}^{frac{nm}{2}} {C_{nm}^{2i} * x^{2i} * y^{nm-2i}} ]

二项式展开(把 (y) 的幂按奇和偶分开):

[(x+y)^{n}=sum_{i=0}^{n/2}{C_{n}^{2i}x^{2i}y^{n-2i}}+sum_{i=1}^{n/2}{C_{n}^{2*i-1}x^{2i-1}y^{n-2i+1}} ]

[(x-y)^{n}=sum_{i=0}^{n/2}{C_{n}^{2i}x^{2i}y^{n-2i}}-sum_{i=1}^{n/2}{C_{n}^{2*i-1}x^{2i-1}y^{n-2i+1}} ]

两式相加,再除 (2),即可得到所求答案。

代码 (1)

C++:

#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
const int inv=499122177;
typedef long long ll;
ll power(ll a,ll b)
{
    ll res=1;
    a%=mod;
    while(b)
    {
        if(b&1)
            res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res%mod;
}
int main()
{
    ll n,m,L,R;
    scanf("%lld%lld%lld%lld",&n,&m,&L,&R);
    if((n*m)&1)
        printf("%lld
",power(R-L+1,n*m));
    else
    {
        ll x=(R-L+1)/2;
        ll y=(R-L+1)-x;
        printf("%lld
",(power(x+y,n*m)+power(x-y,n*m))%mod*inv%mod);
    }
    return 0;
}

python:

mod=998244353
n,m,L,R=map(int,input().split())
if (n*m)%2==1:
    print(pow(R-L+1,n*m,mod))
else:
    x=int((R-L+1)/2)
    y=(R-L+1)-x
    print((pow((x+y),n*m,mod)+pow((x-y),n*m,mod))%mod*pow(2,mod-2,mod)%mod)

代码 (2)

基于上面的个公式,可以发现:
((R-L+1)) 为偶数时,((x-y)=0)
((R-L+1)) 为奇数时,((x-y)=1)
因此可以简化上面的式子。
C++:

#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
const int inv=499122177;
typedef long long ll;
ll power(ll a,ll b)
{
    ll res=1;
    a%=mod;
    while(b)
    {
        if(b&1)
            res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res%mod;
}
int main()
{
    ll n,m,L,R;
    scanf("%lld%lld%lld%lld",&n,&m,&L,&R);
    if((n*m)&1)
        printf("%lld
",power(R-L+1,n*m));
    else if((R-L+1)%2==0)
        printf("%lld
",power(R-L+1,n*m)*inv%mod);
    else
        printf("%lld
",(power(R-L+1,n*m)+1)%mod*inv%mod);
    return 0;
}

python:

mod=998244353
n,m,L,R=map(int,input().split())
if (n*m)%2==1:
    print(pow(R-L+1,n*m,mod))
elif (R-L+1)%2==0:
    print(pow(R-L+1,n*m,mod)*pow(2,mod-2,mod)%mod)
else:
    print((pow(R-L+1,n*m,mod)+1)%mod*pow(2,mod-2,mod)%mod)
原文地址:https://www.cnblogs.com/1024-xzx/p/12636409.html