zoukankan      html  css  js  c++  java
  • 【BZOJ1925】[SDOI2010]地精部落(动态规划)

    【BZOJ1925】[SDOI2010]地精部落(动态规划)

    题面

    BZOJ
    洛谷

    题解

    一道性质(dp)题。(所以当然是照搬学长PPT了啊
    先来罗列性质,我们称题目所求的序列为抖动序列:

    • 一个抖动序列的连续子序列还是一个抖动序列。
    • 如果在一个抖动序列中(x)(x+1)不相邻,那么交换两者的位置这个序列仍是抖动序列。
    • 如果将一个抖动序列中所有大于(x)的元素全部(+1),那么这个序列仍然是抖动序列。
    • 一个([1,x])的抖动序列可以映射到一个([y-x+1,y])的抖动序列。

    上面的性质都比较显然。证明什么的感性理解一下就好了。
    现在来写(dp)
    (f[i][j])表示([1,i])构成的排列中,第一个数为(j)的抖动序列的个数,并且强制第一个数大于第二个数,即第一个位置上是一个峰。
    第一个数这已经确定,现在考虑第二个位置上的数。
    如果这个数不是(j-1),那么我们必定可以交换(j)以及(j-1),不难发现这样子是一一对应的,也就是(f[i][j]leftarrow f[i][j-1])
    否则这个数是(j-1)。那么我们先把第一个(j)个忽视掉,剩下的部分的值是([1,j-1]cup[j+1,i]),那么我们这样子想,我们只需要剩下的这些值离散,变成了([1,i-1]),然后构成了一个以(j-1)开头的抖动序列,再把([j+1,i-1])这一段全部加一,最后再把(j)放回到开头,这样子就可以得到一个抖动序列了。但是我们似乎没法直接从(f[i-1][j-1])转移过来,因为在上述状态中(j-1)是一个峰,但是在(f[i][j])的状态中,(j-1)是一个谷。然而并没有什么关系,我们用上面的最后一个结论,把所有的数全部映射一下,即(j-1)映射到(i-j+1)。那么就可以得到(f[i][j]leftarrow f[i-1][i-j+1])

    那么这样子就可以(dp)了,转移方程是(f[i][j]=f[i][j-1]+f[i-1][i-j+1])
    那么答案就是(sum f[n][i])啦,但是别忘了这样子强制了第一个位置是峰,再映射一下,发现还要乘个二就可以把谷的贡献给算进来啦。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,MOD,f[2][4250],ans;
    int main()
    {
    	scanf("%d%d",&n,&MOD);f[0][1]=1;
    	for(int i=1,nw=1,pw=0;i<=n;++i,nw^=1,pw^=1)
    		for(int j=1;j<=i;++j)
    			f[nw][j]=(f[nw][j-1]+f[pw][i-j+1])%MOD;
    	for(int i=1;i<=n;++i)ans=(ans+f[n&1][i])%MOD;
    	ans=(ans+ans)%MOD;printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    CDH5.13 集成Kerberos配置
    使用bash脚本删除文件最后几行
    yolov3模型微调(fine-tune)备忘
    ubuntu 18.04 rsync 命令使用 服务端配置
    python 子包调用 跨目录调用
    [转]命令行界面 (CLI)、终端 (Terminal)、Shell、TTY的联系与区别
    bash shell 判断变量是否在列表中
    TensorFlow 图像分类模型 inception_resnet_v2 模型导出、冻结与使用
    numpy 数组集合运算及下标操作
    Win10 Service'MongoDB Server' failed to start. Verify that you have sufficient privileges to start system services【简记】
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9837940.html
Copyright © 2011-2022 走看看