AtCoder AGC035F Two Histograms (组合计数、容斥原理)

题目链接

https://atcoder.jp/contests/agc035/tasks/agc035_f

题解

B题难度的F题……然而我还是不会
假设第\(i\)行染的长度是\(a_i\), 第\(j\)列是\(b_j\)
考虑什么情况下两种方案会重复: 若存在\(i,j\)使得\(a_i+1=j\)\(b_j=i\), 那么令\(a'_i=j-1,b'_j=i+1\)可以得到一样的结果。
那么我们也就是要计算不存在\(a_i+1=j\)\(b_j=i\)的序列\(a,b\)个数。
充分性证明: 设存在两个不同的方案\(a,b\)\(a',b'\)满足上面的条件且产生了同样的结果。设\(j\)为最小的满足\(b_j\ne b'_j\)的位置。若\(j=1\)则结论显然成立,若\(j>1\)则有\(a_{b'_j}\ge j\)\(a'_{b'_j}\le j-1\), 又因为\(a'_{b'_j}\ne j-1\)\(a'_{b'_j}\le j-2\). 因此\(a'_{b'_j}\lt j-1\lt a_{b'_j}\). 又因为\(b_{j-1}=b'_{j-1}\),两矩阵第\(b'_j\)行第\((j-1)\)列不可能相等,矛盾。
然后容斥一下就好: \(\sum^{\min(n,m)}_{k=0}(-1)^k{m\choose k}{n\choose k}k!(m+1)^{n-k}(n+1)^{m-k}\)
时间复杂度\(O(n+m)\).

代码

#include
#define llong long long
using namespace std;

inline int read()
{
    int x = 0,f = 1; char ch = getchar();
    for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    return x*f;
}

const int N = 5e5;
const int P = 998244353;
llong fact[N+3],finv[N+3];
int n,m;

llong quickpow(llong x,llong y)
{
    llong cur = x,ret = 1ll;
    for(int i=0; y; i++)
    {
        if(y&(1ll<=0; i--) finv[i] = finv[i+1]*(i+1ll)%P;
    scanf("%d%d",&n,&m); int lim = min(n,m); llong pwn = quickpow(n+1,m-lim),pwm = quickpow(m+1,n-lim); llong ans = 0ll;
    for(int i=lim; i>=0; i--)
    {
        llong cur = comb(m,i)*comb(n,i)%P*fact[i]%P*pwn%P*pwm%P;
        if(i&1) {ans = (ans-cur+P)%P;} else {ans = (ans+cur)%P;}
        pwn = pwn*(n+1ll)%P,pwm = pwm*(m+1ll)%P;
    }
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(AtCoder AGC035F Two Histograms (组合计数、容斥原理))