C/C++教程

AT4119 [ARC096C] Everything on It

本文主要是介绍AT4119 [ARC096C] Everything on It,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

https://www.luogu.com.cn/problem/AT4119

你说原来那个题面蛮好的你换了它干什么你告诉我

截一张qiuly神仙的翻译

在这里插入图片描述

换汤不换药啊

设\(f[i]\)表示钦定\(i\)种酱不合法的方案数,直接拿\(ANS=\sum\limits_{i=0}^n \binom{n}{i} (-1)^i f(i) \times 2^{2^{n-i}}\)

因为包含不合法酱的集合下面已经处理了,所以直接把剩下的随便选即可

考虑怎么求\(f(i)\)

设\(g(i,j)\)表示把\(i\)种酱放在\(j\)个碗里且不合法的方案数

可以得到一个显然的转移方程

\[g(i,j)=g(i-1,j-1)+g(i-1,j)\times(j+1) \]

加一是因为还可以不放

然后显然

\[f(i)=\sum_{j=0}^i g(i,j) \times(2^{(n-i)})^j \]

把没钦定的酱也可以加进这\(j\)个碗中,所以\(j\)次方

一步步推,不要急着跳步

code:

#include<bits/stdc++.h>
#define ll long long
#define N 3005
using namespace std;
ll g[N][N], c[N][N];
int n, mod;
ll qpow(ll x, ll y, ll mod) { y %= mod - 1;
    ll ret = 1;
    for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
    return ret;
}
int main() {
    scanf("%d%d", &n, &mod);
    for(int i = 0; i <= n; i ++) c[i][0] = g[i][0] = 1;
    for(int i = 1; i <= n; i ++) 
        for(int j = 1; j <= i; j ++) 
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod,
            g[i][j] = (g[i - 1][j - 1] + 1ll * (j + 1) * g[i - 1][j] % mod) % mod;
    
    // for(int i = 1; i <= n; i ++) {
    //     for(int j = 0; j <= n; j ++) printf("%lld ", g[i][j]); printf("\n");
    // }
    ll ans = 0;
    for(int i = 0; i <= n; i ++) {
        ll ret = 0;
        for(int j = 0; j <= i; j ++) (ret += g[i][j] * qpow(2, 1ll * (n - i) * j, mod) % mod) %= mod;
        ret = ret * c[n][i] % mod * qpow(2, qpow(2, n - i, mod - 1), mod) % mod;
    //    printf("%lld ", ret);
        if(i & 1) ans = (ans - ret + mod) % mod;
        else ans = (ans + ret) % mod;
    }
    printf("%lld", ans);
    return 0;
}
这篇关于AT4119 [ARC096C] Everything on It的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!