zoukankan      html  css  js  c++  java
  • AGC024E Sequence Growing Hard

    题意

    给出(n),(m),(mu),问有多少个序列组((A_0,A_1,dots,A_n))满足:

    • 序列(Ai)的长度恰好为(i)
    • 所有元素均在([1,m])
    • (A_{i−1})(A_i)的子序列
    • (A_i)的字典序大于(A_{i−1})

    答案模(mu)输出。
    (n,k le 300)
    传送门

    思路

    又是一道神仙(dp)
    一个很重要的思路:把数从小往大插入
    当我们插入(i)时,因为数列中的数都是(le i)的,所以(i)插在所有位置都是可以的
    例如:(1323),考虑插入(3)
    最前面:(31323);一:(13323);二:(13323);三:(13233);四:(13233)
    不过同时我们也发现:会算重。而且是当插到(i)前面的时候
    所以我们强行规定相同数一定要插在后面就可以了。
    我们记录(dp[i][j][k])表示当前进行到第(i)个操作,放到数字(j),有(k)个数后可以放(注意这意味着有(k+1)种,因为开头也是可以放的)。
    转移:

    • (dp[i][j][k - 1]+= dp[i][j][k] (k>0))表示这个位置的数后不放
    • (dp[i][j + 1][i] += dp[i][j][k] (k=0))(j)已经不能放了,从(j+1)新开始放(不存在相同的,所以所有数后都能放)
    • (dp[i + 1][j][k] += dp[i][j][k]*(k + 1)) 表示我们放置这个数,放这个数有(k+1)中选择。

    代码十分简短
    参考

    #include <bits/stdc++.h>
    #define upd(x,y) x=(x+y>=mu?x+y-mu:x+y)
    int n,m,mu,dp[305][305][305];
    int main(){
    	scanf("%d%d%d",&n,&m,&mu);
    	dp[0][1][0]=1;
    	for (int i=0;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			for (int k=i;k>=0;k--){
    				if (k) upd(dp[i][j][k-1],dp[i][j][k]);
    				else upd(dp[i][j+1][i],dp[i][j][k]);
    				upd(dp[i+1][j][k],1ll*dp[i][j][k]*(k+1)%mu);
    			} 
    	printf("%d",dp[n][m][0]);
    }
    
    * 生而自由 爱而无畏 *
  • 相关阅读:
    架构阅读笔记9
    架构阅读笔记8
    架构阅读笔记7
    架构阅读笔记6
    架构阅读笔记5
    git安装使用详解
    mysql主从
    人定胜天
    jquery即点击改
    无限极分类/数组处理
  • 原文地址:https://www.cnblogs.com/flyfeather6/p/11778415.html
Copyright © 2011-2022 走看看