• CCPC-Wannafly Winter Camp Day4 Div1


    题目链接:https://zhixincode.com/contest/18/problem/G?problem_id=265

    题目描述

    wls有一个整数 $n$,他想请你算一下有多少 $1...n$ 的排列(permutation)满足:对于所有的 $i(2 le i le n)$,若 $i$ 为奇数,则 $a[i−1]<a[i]$,否则 $a[i−1]>a[i]$。请输出答案 $mod 1e9 + 7$。

    输入描述

    一行一个整数 $n$。

    $1≤n≤1000$

    输出描述

    一行一个整数表示答案。

    样例输入 1

    3
    样例输出 1

    2

    题解:

    这个数大概叫 up/down number ?参见OEIS:https://oeis.org/A000111

    $dp[i][j]$ 表示前 $i$ 个满足字符串条件的结尾为 $j$ 的 $i$ 的排列,这里需要注意的是 $1 sim i$ 的排列。

    那么,如果第 $i$ 位是奇数位(山峰),$dp[i][j] = dp[i-1][1] + dp[i-1][2] + cdots + dp[i-1][j-1]$。这个是很明显的。

    那么,如果第 $i$ 位是偶数位(山谷),$dp[i][j] = dp[i-1][j] + dp[i-1][j+1] + cdots + dp[i-1][i-1]$。因为要令当前位为 $j$,那么如果前面出现过大于等于 $j$ 的数字,就令这些数字全部加上 $1$,就能构造出排列。

    这样的话,枚举 $i$,然后枚举 $j$,对于每个 $dp[i][j]$ 还需要 $O(n)$ 计算,这样一来就是 $O(n^3)$ 的时间复杂度,用前缀和可以优化到 $O(n^2)$。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1005;
    const int mod=1e9+7;
    
    int n;
    ll dp[maxn][maxn],sum[maxn][maxn];
    
    int main()
    {
        cin>>n;
        sum[1][1]=dp[1][1]=1;
        for(int i=2;i<=n;i++)
        {
            for(int j=1;j<=i;j++)
            {
                if(i%2) //奇数
                {
                    dp[i][j]=sum[i-1][j-1];
                    sum[i][j]=sum[i][j-1]+dp[i][j], sum[i][j]%=mod;
                }
                else //偶数
                {
                    dp[i][j]=(sum[i-1][i-1]-sum[i-1][j-1]+mod)%mod;
                    sum[i][j]=sum[i][j-1]+dp[i][j], sum[i][j]%=mod;
                }
            }
        }
        cout<<sum[n][n]<<endl;
    }
  • 相关阅读:
    关于发布版本号管理
    WWF
    C#编码规范和命名规则
    使用正则表达式更改编译版本号
    .net2005登录控件
    读取web.config自定义配置节
    在SQL SERVER 2005 中使用XML
    CVSNT用户权限配置
    共享鼠标
    《Ajax基础教程》
  • 原文地址:https://www.cnblogs.com/dilthey/p/10406433.html
Copyright © 2020-2023  润新知