• 洛谷 P2513 [HAOI2009]逆序对数列


    题目描述

    对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数。若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数。那么逆序对数为k的这样自然数数列到底有多少个?

    输入输出格式

    输入格式:

    第一行为两个整数n,k。

    输出格式:

    写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果。

    输入输出样例

    输入样例#1:
    4 1
    输出样例#1:
    3

    说明

    样例说明:

    下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;

    测试数据范围

    30%的数据 n<=12

    100%的数据 n<=1000,k<=1000

    一道简单题,但我觉得可以做到更大的数据,比方说加两个0

    从小到大考虑每一位,先考虑1,如果1位于i这个位置,那1与1~i-1这些位置的每一个数都会产生一个逆序对,与i+1~n这些位置的数都不会产生逆序对,至于具体每个数字是什么对于1的贡献没有影响

    然后从排列里把1去掉,变成一个2~n的排列,这个排列与1~n-1的排列是等价的,于是问题转化成了一个较小的问题

    然后可以dp

    dp[i][j]表示1~i的排列,要有j个逆序对的方法数,枚举当前位置产生的逆序对来转移,这个东西本来是nk^2的,但是发现一个位置转移的时候是连续的一段,用前缀和优化去掉一个k即可

    其实这个问题等价于有n个带编号的盒子排成一列,一共放k个球,标号为i的盒子里不能放超过i-1个球,求方法总数,这应该是有更好的做法的

    UPD1:这个东西的生成函数是 $ (1)(1+x)(1+x+x^2)(1+x+x^2+x^3)...(1+x+x^2+...+x^{n-1}) $ 即 $ prod_{p=1}^{n}sum_{q=0}^{p-1}x^q $ ,这个形式过于美妙让人很难不认为它有一个优美的通解

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <string>
     6 #include <cstring>
     7 #include <cmath>
     8 #include <map>
     9 #include <stack>
    10 #include <set>
    11 #include <vector>
    12 #include <queue>
    13 #include <time.h>
    14 #define eps 1e-7
    15 #define INF 0x3f3f3f3f
    16 #define MOD 10000
    17 #define rep0(j,n) for(int j=0;j<n;++j)
    18 #define rep1(j,n) for(int j=1;j<=n;++j)
    19 #define pb push_back
    20 #define mp make_pair
    21 #define set0(n) memset(n,0,sizeof(n))
    22 #define ll long long
    23 #define ull unsigned long long
    24 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
    25 #define max(a,b) (a>b?a:b)
    26 #define min(a,b) (a<b?a:b)
    27 #define print_runtime printf("Running time:%.3lfs
    ",double(clock())/1000.0)
    28 #define TO(j) printf(#j": %d
    ",j);
    29 //#define OJ
    30 using namespace std;
    31 const int MAXINT = 100010;
    32 const int MAXNODE = 100010;
    33 const int MAXEDGE = 2*MAXNODE;
    34 char BUF,*buf;
    35 int read(){
    36     char c=getchar();int f=1,x=0;
    37     while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
    38     while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    39     return f*x;
    40 }
    41 char get_ch(){
    42     char c=getchar();
    43     while(!isalpha(c)) c=getchar();
    44     return c;
    45 }
    46 //------------------- Head Files ----------------------//
    47 
    48 int n,k;
    49 int dp[10010],sum[10010];
    50 void get_input();
    51 void work();
    52 int main() {
    53     get_input();
    54     work();
    55     return 0;
    56 }
    57 void work(){
    58     fill(sum,sum+k+1,1);
    59     for(int i=2;i<=n;i++){ //box no i,can take 0~i-1
    60         rep0(j,k+1){
    61             dp[j] = (j-i+1>0?sum[j]-sum[j-i]:sum[j]);
    62         }
    63         sum[0]=dp[0];
    64         rep1(j,k){
    65             sum[j]=(sum[j-1]+dp[j])%MOD;
    66         }
    67     }
    68     printf("%d
    ",(dp[k]+MOD)%MOD);
    69 }
    70 void get_input(){
    71        n=read();k=read();
    72 }
  • 相关阅读:
    博客园作业 04
    C语言II博客作业02
    C语言II博客作业01
    linux找不到动态链接库.so文件的解决方法
    工厂模式
    markdown基本语法
    IDEA解决file://无法访问问题,构建虚拟路径方法
    python 制作伪switch(不过认为更加麻烦,使用起来不方便,不如跟随python使用if更轻巧)
    python 读取编码为UTF-8-BOM文件(如果一直出现读取失败,可以尝试用记事本查看文件的编码格式,且可以读取任何文件格式)
    python 读取excel方法(最大行数:1048576)
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6921138.html
Copyright © 2020-2023  润新知