zoukankan      html  css  js  c++  java
  • [CEOI2016]kangaroo

    前言:(OI)中有一些奇思妙想,可能第一次自己想不出来,不要懊恼,不要沮丧,认真地去学习它,下次遇到就不怕了_

    正文:考虑(dp),设状态量(dp[i][j])表示前(i)个数分(j)段(任意一段满足条件)的方法数。

    先给出状态转移方程:

    [dp[i][j]=(j-c)*dp[i-1][j-1]+j*dp[i-1][j+1]quad i e s,i e t,c=(i>s)+(i>t) ]

    [dp[i][j]=dp[i-1][j-1]+dp[i-1][j]quad i=squad orquad i=t ]

    原因解释:

    1.(i e s,i e t)时,可将(i)单独成段,插在任意位置(若(s)以过则不能插首,若(t)已过则不能插尾),则贡献为((j-c)*dp[i-1][j-1])

    或将(i)用于两段的合并,插在任意夹缝中,易知(i)比两段大,故操作合法,贡献为(j*dp[i-1][j+1])

    2.(i=squad orquad i=t)时,(i)只能放在首或尾,可与相邻段落合并,可单独成段,故贡献为(dp[i-1][j-1]+dp[i-1][j])

    代码如下,仅供参考:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e3+10;
    const int mod=1e9+7;
    int n,s,t;
    ll dp[maxn][maxn];
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	return x*f;
    }
    int main(){
    	n=read();s=read(),t=read();
    	dp[1][1]=1;
    	for(int i=2;i<=n;i++)
    		if(i!=s&&i!=t)
    			for(int j=1;j<=i;j++)
    				dp[i][j]=(dp[i-1][j-1]*(j-(i>s)-(i>t))+dp[i-1][j+1]*j)%mod;
    		else for(int j=1;j<=i;j++)
    				dp[i][j]=(dp[i-1][j-1]+dp[i-1][j])%mod;
    	printf("%lld
    ",dp[n][1]);
    	return 0;
    }
    

    深深地感到自己的弱小。

  • 相关阅读:
    记一次在Windows10桌面环境搭建Jekins的吐血经历
    Windows系统下的输入法选择
    Linux后台进程启停脚本模板
    crontab采坑总结
    编程软件仓库集合
    CentOS7安装Chrome及驱动
    不错的“淘宝”网站
    软件下载网站集合
    在线API集合
    在线教程集合
  • 原文地址:https://www.cnblogs.com/syzf2222/p/13837119.html
Copyright © 2011-2022 走看看