zoukankan      html  css  js  c++  java
  • 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)
    
  • 相关阅读:
    XmlDocument.selectNodes() and selectSingleNode()的xpath的学习资料
    config相关操作(转)
    网站存储session的方案
    VS2015 C#6.0 中的那些新特性(转自http://www.cnblogs.com/henryzhu/p/new-feature-in-csharp-6.html)
    ERROR L105: PUBLIC REFERS TO IGNORED SEGMENT 的解决办法
    关于C51内的code,idata,xdata
    KeilC51使用详解 (三)
    KeilC51使用详解 (二)
    KeilC51使用详解 (一)
    变量初始化
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/12636409.html
Copyright © 2011-2022 走看看