zoukankan      html  css  js  c++  java
  • Bzoj 2431 HAOI2009 逆序对数列

    Description
    对于一个数列{ai},如果有i**<**j且ai>aj,那么我们称ai与aj为一对逆序对数。若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数。那么逆序对数为k的这样自然数数列到底有多少个?
    Input
    第一行为两个整数n,k。
    Output
    写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果。
    Sample Input
    样例输入
    4 1
    Sample Output
    样例输出
    3
    样例说明:
    下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;
    测试数据范围
    30%的数据 n<=12
    100%的数据 n<=1000,k<=1000

    /*
    暴力n^3.
    30分.  
    */
    #include<iostream>
    #include<cstdio>
    #define MAXN 10001
    #define mod 1000000007
    using namespace std;
    int f[MAXN][MAXN],n,m;
    int main() {
        scanf("%d %d",&n,&m);
        f[1][0]=1;
        for(int i=1; i<=n; i++)
            for(int j=0; j<=m; j++)
                for(int k=0; k<i; k++) 
                {
                    f[i][j]+=f[i-1][j-k];
                    f[i][j]%=mod;
                }
        printf("%d ",f[n][m]);
        return 0;
    }
    /*
    中学生不能太暴力.
    so  我们考虑优化.
    DP暴力n^3完全能搞出来.
    然后我们发现转移的时候
    对于i状态只有i-1状态转移而来.
    我们考虑类似于滚动数组之类的东西.
    so 处理一个前缀和.
    f[i][j]表示i个数j个逆序对时的方案数.
    对于第i个数来说,若是递增序放置的
    那么 i放置位置的后面每个数都可以与i形成一对逆序对. 
    */
    #include<iostream>
    #include<cstdio>
    #define MAXN 10001
    #define mod 1000000007
    using namespace std;
    long long f[MAXN][MAXN],n,m,tot;
    int main() 
    {
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
          f[i][0]=1;
        for(int i=2;i<=n;i++)
        {
          tot=f[i-1][0];
          for(int j=1;j<=m;j++)
            {
                if (j>=i) tot-=f[i-1][j-i];
                tot+=f[i-1][j];
                f[i][j]=tot%mod;
            }
        }
        printf("%d",f[n][m]);
        return 0;
    }
  • 相关阅读:
    61序列化二叉树
    60把二叉树打印成多行
    59按之字形顺序打印二叉树
    58对称的二叉树
    57二叉树的下一个结点
    56删除链表中重复的结点
    55链表中环的入口结点
    Python100天打卡-Day10
    Python100天打卡
    点至直线的距离和垂足点计算
  • 原文地址:https://www.cnblogs.com/nancheng58/p/6070828.html
Copyright © 2011-2022 走看看