ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOIP 模拟赛 长寿花 题解

2022-08-18 20:32:52  阅读:157  来源: 互联网

标签:长寿 le NOIP int 题解 sum times 1ll op


NOIP 模拟赛 长寿花 题解

要放 \(n\) 层物品,第 \(i\) 层有 \(a_i\) 个位置放物品,物品有 \(m\) 中颜色,有约束条件:

  • 同一层两个相邻物品颜色不能相同。
  • 相邻两层颜色集合不能相同。

求方案数 \(\pmod p\)

\(n,m\le 10^6,a_i\le 5000,\sum_{i=1}^n a_i\le 10^7,p\le 10^9\)

sol

由于总颜色数不变,可以先不管选了哪些颜色,最后乘上一个组合即可。

设 \(g_{i,j}\) 为对于某一行,前 \(i\) 个位置用了 \(j\) 个颜色方案数。

\[g_{i,j}=g_{i-1,j-1}\times j + g_{i-1,j}\times (j-1) \]

由于后面需要求组合数,稍加修改这个递推式可以简化实现:

\[g_{i,j}=g_{i-1,j-1} + g_{i-1,j}\times (j-1) \]

那么原来的 \(g_{i,j}\) 等于现在的 \(g_{i,j}\times j!\)

设 \(f_{i,j}\) 为前 \(i\) 层,第 \(i\) 行放了 \(j\) 种颜色的方案数。

\[f_{i,j}=g_{a_i,j}\times j!\times\left(C_m^j\times\sum_{k=1}^{a_{i-1}} f_{i-1,k} -f_{i-1,j}\right) \]

由于有组合数, \(P\) 也不一定是质数,分解质因数麻烦,这就体现修改后的用处了。

\(j!\times\binom{m}{j}=\dfrac{m!}{(m-j)!}\) ,是可以预处理的。

最后, \(f\) 滚掉一维,那个 \(\sum\) 用前缀和。最终复杂度 \(O(\sum a_i)\)

code

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long uLL;
typedef long double LD;
typedef double db;
const int N = 1e6 + 5;
int n, m, a[N], mx, op, vis[N], P;
int f[2][5005], g[5005][5005], fac[N], o[N];
int main() {
    scanf("%d%d%d", &n, &m, &P);
    fac[0] = 1, o[0] = 1;
    for (int i = 1; i <= m; i++) fac[i] = 1ll * fac[i - 1] * i % P, o[i] = 1ll * o[i - 1] * (m - i + 1) % P;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        mx = max(mx, a[i]);
    }
    g[0][0] = 1;
    for (int i = 1; i <= mx; i++)
        for (int j = 1; j <= mx && j <= m; j++)
            g[i][j] = (1ll * g[i - 1][j - 1] % P + 1ll * g[i - 1][j] * (j - 1) % P) % P;
    f[0][0] = 1;
    for (int i = 1, j; i <= n; i++) {
        op ^= 1;
        memset(f[op], 0, sizeof(f[op]));
        for (j = 1; j <= a[i] && j <= m; j++) {
            f[op][j] = 1ll * g[a[i]][j] * f[op ^ 1][0] % P * o[j] % P;
            if (a[i - 1] >= j) f[op][j] = 1ll * (f[op][j] - 1ll * f[op ^ 1][j] * g[a[i]][j] % P * fac[j] % P) % P;
            f[op][0] = 1ll * (f[op][0] + f[op][j]) % P;
        }
    }
    printf("%d", 1ll * (f[op][0] + P) % P);
}

标签:长寿,le,NOIP,int,题解,sum,times,1ll,op
来源: https://www.cnblogs.com/KonjakLAF/p/16599987.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有