zoukankan      html  css  js  c++  java
  • codeforces 997C.Sky Full of Stars

    题目链接:codeforces 997C.Sky Full of Stars

    一道很简单(?)的推式子题

    直接求显然不现实,我们考虑容斥

    (f(i,j))为该方阵中至少有(i)行和(j)列为相同颜色的情况

    那么显然有(ans=sum_{i=0}^n sum_{j=0}^n C_n^i C_n^j (-1)^{i+j-1} f(i,j) (i+j eq0))

    其中对于(f(i,j))的取值有两种情况

    ​ I.若(i=0)(j=0),先假设(i=0),那么颜色相同的(j)列的颜色可以随意变化,故(f(i,j)=f(0,j)=3^j*3^{n(n-j)})

    ​ II.若(i eq0 && j eq0),那么这(i)行和(j)列的颜色一定是相同的,故(f(i,j)=3*3^{(n-i)(n-j)})

    对于I,我们可以在(O(nlogn))的时间内求出结果

    对于II,我们可以通过预处理在(O(n^2))的时间内求出结果,但这显然是不可行的,于是我们考虑变形

    根据3的幂次我们令(i=n-i,j=n-j)

    那么原式=(sum_{i=0}^{n-1} sum_{j=0}^{n-1} C^{n-i}_n C^{n-j}_n (-1)^{2n-i-j-1} 3*3^{ij})

    =(3sum_{i=0}^{n-1} sum_{j=0}^{n-1} C^{i}_n C^{j}_n (-1)^{i+j+1} 3^{ij})

    这样做的话仍然没有结束,我们考虑将(i)提出来

    原式=(3sum_{i=0}^{n-1} C_n^i (-1)^{i+1} sum_{j=0}^{n-1} C_n^j (-1)^j 3^{ij})

    =(3sum_{i=0}^{n-1} C_n^i (-1)^{i+1} sum_{j=0}^{n-1} C_n^j (-3^i)^j)

    由二项式定理知,原式=(3sum_{i=0}^{n-1} C_n^i (-1)^{i+1} [(1+(-3^i))^n-(-3^i)^n])

    这样的话我们也能在(O(nlogn))的时间内求出这个值

    总时间复杂度(O(nlogn))

    #include<iostream>
    #include<string>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    using namespace std;
    #define rep(i,a,b) for (i=a;i<=b;i++)
    typedef long long ll;
    #define maxd 998244353
    
    ll qpow(ll x,ll y)
    {
        ll ans=1,sum=x;
        while (y)
        {
            int tmp=y%2;y/=2;
            if (tmp) ans=(ans*sum)%maxd;
            sum=(sum*sum)%maxd;
        }
        return ans;
    }
    
    int n;
    ll c[1001000],inv[1001000];
    
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    void init()
    {
        n=read();int i;
        c[0]=1;inv[1]=1;
        for (i=2;i<=n;i++) inv[i]=((maxd-maxd/i)*inv[maxd%i])%maxd;
        for (i=1;i<=n;i++) c[i]=((c[i-1]*(n-i+1))%maxd*inv[i])%maxd;
        //for (i=1;i<=n;i++) cout << c[i] << " ";cout << endl;
    }
    
    void work()
    {
        ll ans=0,ans1=0,ans2=0;int i;
        for (i=1;i<=n;i++)
        {
            if (i%2) ans1+=(c[i]*qpow(3,(ll)n*(n-i)+i))%maxd;
            else ans1-=(c[i]*qpow(3,(ll)n*(n-i)+i))%maxd;
        }
        for (i=0;i<n;i++)
        {
            if (i%2) ans2+=(c[i]*(qpow(1+maxd-qpow(3,i),n)-qpow(maxd-qpow(3,i),n))%maxd)%maxd;
            else ans2-=(c[i]*(qpow(1+maxd-qpow(3,i),n)-qpow(maxd-qpow(3,i),n))%maxd)%maxd;
        }
        ans1=((ans1%maxd)+maxd)%maxd;
        ans2=((ans2%maxd)+maxd)%maxd;
        ans=(ans1*2+ans2*3)%maxd;
        printf("%I64d",ans);
    }
    
    int main()
    {
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    JS中的一些遍历方法
    JS中关于引用类型数据及函数的参数传递
    JS中关于数组的操作
    CSS中的一些伪类
    JS中的回调函数
    JS中关于构造函数、原型链、prototype、constructor、instanceof、__proto__属性
    JDK的安装及环境变量配置
    JS中的this指针
    JS中的数据类型
    Word中页码及目录、参考文献的制做方法
  • 原文地址:https://www.cnblogs.com/encodetalker/p/10154563.html
Copyright © 2011-2022 走看看