zoukankan      html  css  js  c++  java
  • Codeforces 140E(排列组合、dp)

    要点

    • 主要学到的东西:一个序列染色,相邻不染同色,恰用(j)种颜色的1.模式数2.方案数3.具体染色数
    • 从大的思路上来讲:先dp预处理出每一层的模式数:(f[i][j])表示(i)个位置恰染(j)个颜色的模式数,然后再dp出各层之间的转移:(dp[i][j])表示(i)层恰染(j)个颜色的具体染色数,用上一轮的答案乘上这一层的具体染色数(是(f[l[i]][j]*A_m^j)再减去这层和上层重复的。
    • 我将染色的阶段分为三个阶段。虽然题目中总是让求方案数但不同的题需要的是不同阶段的方案数。
    • 第一阶段是模式数:即如果有三个位置,你决定填充的是“红绿红”和“绿红绿”其实是一样的“模式”。本题预处理的就是模式:(f[i][j] = f[i-1][j-1]+f[i-1][j]*(j-1)),意义是前i-1个如果已经有使用过j-1种类型,则这个位置是唯一的(*1);如果前i-1个已经使用过j种类型,则当前的只要和相邻的左边这个不同即可。
    • 第二阶段是方案数,即“这个类型用第几个颜色去填充它”,更具体了一些。这时“红绿红”和“绿红绿”就是典型的两种方案。第二阶段的计算方法是:(f[i][j]*j!)。之前做的一道题GYM 101933K他官方题解的做法(方法二)就是直接进行第二阶段的记忆化搜索,我用这套理论先递推第一阶段再做第二阶段(乘个阶乘),果然也是对的。
    • 第三阶段是具体染色数,即真的给了赤橙黄绿青蓝紫然后选若干个去染,就最最具体的阶段了。计算方法:(f[i][j]*j!*C_m^j=f[i][j]*A_m^j)
    • 这些还没说完orz……这题真的想了很久。回到本题,其中扣掉“这层和上层重复的”这里我觉得有必要想一想,扣的方案数是第几阶段的方案数?正解是(dp[i][j]-dp[i-1][j]*j!*f[l[i]][j]),为什么是(j!)而不是(A_m^j)或者(C_m^j)呢?因为当你已经计算完上一层的方案数之时,回想数学课学习的排列组合知识,是不是就假定了上一层已经固定了?虽然不知道固定的是谁,但是他已经有了一定了。所以这一层如果跟上一层颜色集重合的话,就是(1*方案数),即上一层如果是“红绿”的话,这一层也只有选择“红绿”时才会和它重,所以只扣一份的即可。
    #include <cstdio>
    
    const int maxn = 1e6 + 5;
    int n, m, p, l[maxn];
    int f[5005][5005], A[5005], fac[5005];
    int dp[2][5005], ans[2];
    
    void Read() {
    	scanf("%d %d %d", &n, &m, &p);
    	for (int i = 1; i <= n; i++)
    		scanf("%d", &l[i]);
    }
    
    void Pre() {
    	f[0][0] = 1;
    	for (int i = 1; i <= 5000; i++)
    		for (int j = 1; j <= i; j++)
    			f[i][j] = (1LL * f[i - 1][j - 1] + 1LL * f[i - 1][j] * (j - 1) % p) % p;
    
    	fac[0] = A[0] = 1;
    	for (int i = 1; i <= 5000; i++) {
    		fac[i] = 1LL * fac[i - 1] * i % p;
    		A[i] = 1LL * A[i - 1] * (m - i + 1) % p;
    	}
    }
    
    void Solve() {
    	ans[0] = 1;
    	for (int i = 1; i <= n; i++) {
    		ans[i & 1] = 0;
    		for (int j = 1; j <= l[i]; j++) {
    			dp[i & 1][j] = 1LL * A[j] * f[l[i]][j] % p * ans[(i - 1) & 1] % p;
    			if (j <= l[i - 1]) {
    				int out = 1LL * dp[(i - 1) & 1][j] * fac[j] % p * f[l[i]][j] % p;
    				dp[i & 1][j] = (dp[i & 1][j] - out + p) % p;
    			}
    			
    			ans[i & 1] = (ans[i & 1] + dp[i & 1][j]) % p;
    		}
    	}
    }
    
    int main() {
    	Read();
    	Pre();
    	Solve();
    	return !printf("%d
    ", ans[n & 1]);
    }
    
  • 相关阅读:
    Educational Codeforces Round 83 --- F. AND Segments
    Educational Codeforces Round 83 --- G. Autocompletion
    SEERC 2019 A.Max or Min
    2019-2020 ICPC Southwestern European Regional Programming Contest(Gym 102501)
    Educational Codeforces Round 78 --- F. Cards
    今天我学习了一门全新的语言
    codeforces 1323D 题解(数学)
    Educational Codeforces Round 80 (Div. 2) 题解 1288A 1288B 1288C 1288D 1288E
    Educational Codeforces Round 81 (Div. 2) 题解 1295A 1295B 1295C 1295D 1295E 1295F
    Codeforces Round #617 (Div. 3) 题解 1296C 1296D 1296E 1296F
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10895941.html
Copyright © 2011-2022 走看看