zoukankan      html  css  js  c++  java
  • 【CCPC-Wannafly Winter Camp Day4 (Div1) G】置置置换(动态规划)

    点此看题面

    大致题意: 求出有多少个长度为(n)的排列满足对于奇数位(a_{i-1}<a_i),对于偶数位(a_{i-1}>a_i)

    考虑打表?

    考虑每次只有一个数(n),且(nle1000),首先想到的自然是打表。

    打表程序略(其实是手贱不小心删掉了)。

    然后放到(OEIS)上,我们就可以找到一个(Python)的伪代码。

    于是(hl666)神仙就切了此题。

    动态规划

    当然,像我这么弱,不会(Python),只好去写(DP)了。

    我们可以设(f_i)表示有多少个长度为(i)的排列满足条件

    考虑加入一个数(i+1),我们可以把原来一个合法的数列挑选一个位置分成两半,枚举两边的数个数分别为(j)(i-j)

    则两边的情况数其实分别就是(f_j)(f_{i-j}),而(j)个数从(i)个数中的选择方案为(C_i^j)

    但问题在于这样刚好会有一半的情况是不合法的,因此还要再除以(2)

    所以最终的转移方程就是:

    [f_{i+1}=frac{sum_{j=0}^if_jf_{i-j}C_i^j}2 ]

    也就相当于:

    [f_i=frac{sum_{j=0}^{i-1}f_jf_{i-1-j}C_{i-1}^j}2 ]

    初始化(f_0=f_1=1)

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000
    #define X 1000000007
    #define C(x,y) (1LL*Fac[x]*Inv[y]%X*Inv[(x)-(y)]%X)
    #define Qinv(x) Qpow(x,X-2)
    #define Inc(x,y) ((x+=(y))>=X&&(x-=X))
    using namespace std;
    int n,a[N+5],f[N+5],Fac[N+5],Inv[N+5];
    I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}//快速幂
    int main()
    {
    	RI i,j,I2=X+1>>1;for(scanf("%d",&n),Fac[0]=i=1;i<=n;++i) Fac[i]=1LL*Fac[i-1]*i%X;//预处理阶乘
    	for(Inv[n]=Qinv(Fac[n]),i=n-1;~i;--i) Inv[i]=1LL*Inv[i+1]*(i+1)%X;//预处理阶乘逆元
    	for(f[0]=f[1]=1,i=2;i<=n;f[i]=1LL*f[i]*I2%X,++i) for(j=0;j^i;++j) Inc(f[i],1LL*f[j]*f[i-1-j]%X*C(i-1,j)%X);//DP转移
    	return printf("%d",f[n]),0;//输出答案
    }
    
  • 相关阅读:
    一周优化内存、查询速度小结
    三种不同的方式,计算欧氏距离,速度比较
    三种不同的方式,计算欧氏距离,速度比较
    多线程与多进程
    匹配错误分析
    fasttext与Linear SVC 分类测试结果
    什么是闭包
    智能客服功能页面
    客服培训
    约当产量法
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CometOJDay4Div1G.html
Copyright © 2011-2022 走看看