zoukankan      html  css  js  c++  java
  • 【BZOJ2699】更新 动态规划

    【BZOJ2699】更新

    Description

           对于一个数列A[1..N],一种寻找最大值的方法是:依次枚举A[2]到A[N],如果A[i]比当前的A[1]值要大,那么就令A[1]=A[i],最后A[1]为所求最大值。假设所有数都在范围[1, K]内,按上面的步骤执行,有多少个长度N的数列满足A[1]被更新的次数恰好为P呢?

    Input

           本题有多组数据。输入第一行一个数T为数据组数,下面T行每行依次三个数N、K和P。

    Output

           对每组数据输出一行,为方案数模1000000007的值。
     
    输入 输出 解释
    3
    4 3 2
    2 3 1
    3 4 1
    6
    3
    30
    对第一组数据N=4, K=3, P=2, 所有满足的序列有下面六种:
    1) {1,1,2,3}   2) {1,2,1,3}
    3) {1,2,2,3}   4) {1,2,3,1}
    5) {1,2,3,2}   6) {1,2,3,3}
     
    数据范围
           前20%的数据满足T ≤ 5
    前50%的数据满足1 ≤ N ≤ 50,1 ≤ K ≤ 100
           对100%的数据,T ≤ 1000,1 ≤ N ≤ 150,0 ≤ P < N,1 ≤ K ≤ 300

    题解:傻题。。

    用f[i][j][k]表示前i个数,最大值为j,已经被更新了k次的方案数。然后用前缀和优化转移即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    typedef long long ll;
    const ll P=1000000007;
    int T,n,m,p;
    int f[160][310][160];
    int main()
    {
    	int i,j,k;
    	for(i=1;i<=300;i++)	f[1][i][0]=i;
    	for(i=2;i<=150;i++)
    	{
    		for(k=0;k<=150;k++)
    		{
    			for(j=1;j<=300;j++)
    			{
    				if(k)	f[i][j][k]=f[i-1][j-1][k-1];
    				f[i][j][k]=(f[i][j][k]+1ll*j*(f[i-1][j][k]-f[i-1][j-1][k]+P)%P+f[i][j-1][k])%P;
    			}
    		}
    	}
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d%d",&n,&m,&p);
    		printf("%d
    ",f[n][m][p]);
    	}
    	return 0;
    }
  • 相关阅读:
    springboot滚动分页展示列表(类似layui瀑布流效果)
    使用DOS命令运行JAVA项目
    MarkDown基础语法
    Springboot结构梳理
    VO层
    常用注解
    Java注解和反射笔记
    Java网络编程
    原理篇—sql注入5:pikachu靶机练习
    原理篇——sql注入2:联合查询注入
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7787747.html
Copyright © 2011-2022 走看看