发现自己学了几天splay已经傻了

其实还是一个比较裸的dp的,但是还是想了一小会,还sb的wa了几次

首先这道题的状态应该很好看出,我们用\(f[i][j]\)表示在前\(i\)个数中(即\(1-i\)中)逆序对个数为\(j\)的方案数

于是我们考虑怎么转移,我们知道逆序对这个东西并不看重实际的大小,只用关心相对大小就行了

于是\(f[i][j]\)的状态肯定来自于\(f[i-1]\),这就相当于我们向序列里加入了\(i\)

由于\(i\)比之前所有数都大,于是它在几个数的前面就会产生多少个逆序对

于是我们的方程就很好写了

\(f[i][j]=\sum_{p=0}^{j}f[i-1][p]\)

同时前\(i-1\)新产生的逆序对的数量也就是\(i-1\)了

于是对于上面那个方程我们还要有一个限制条件

那就是\(p+i-1>=j\)

于是这份暴力代码就可以写出来了

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #define re register
  5. #define maxn 1001
  6. using namespace std;
  7. const int mod=10000;
  8. int f[maxn][maxn];
  9. int n,k;
  10. inline int read()
  11. {
  12. char c=getchar();
  13. int x=0;
  14. while(c<'0'||c>'9') c=getchar();
  15. while(c>='0'&&c<='9')
  16. x=(x<<3)+(x<<1)+c-48,c=getchar();
  17. return x;
  18. }
  19. int main()
  20. {
  21. n=read();
  22. k=read();
  23. for(re int i=1;i<=n;i++) f[i][0]=1;
  24. for(re int i=1;i<=n;i++)
  25. for(re int j=1;j<=k;j++)
  26. for(re int p=0;p<=j;p++)
  27. if(i-1+p>=j) f[i][j]=(f[i-1][p]+f[i][j])%mod;
  28. cout<<f[n][k]<<endl;
  29. return 0;
  30. }

但这份代码的复杂度显然是\(O(nk^2)\)的,于是就只有70

我们再去看看我们的方程,那是一个和式,下标还是连续的

有没有想到什么快速求和的方法

那自然是前缀和

由于我们更新\(i\)只会用到\(i-1\)

于是我们开一个滚动的前缀和数组就可以了

于是这就是代码了

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #define re register
  5. #define maxn 1001
  6. using namespace std;
  7. const int mod=10000;
  8. int f[maxn][maxn];
  9. int n,k;
  10. int p[2][maxn];
  11. inline int read()
  12. {
  13. char c=getchar();
  14. int x=0;
  15. while(c<'0'||c>'9') c=getchar();
  16. while(c>='0'&&c<='9')
  17. x=(x<<3)+(x<<1)+c-48,c=getchar();
  18. return x;
  19. }
  20. int main()
  21. {
  22. n=read();
  23. k=read();
  24. for(re int i=1;i<=n;i++) f[i][0]=1;
  25. p[0][0]=p[1][0]=1;
  26. int now=0;
  27. for(re int i=1;i<=k;i++)
  28. p[now][i]=1;
  29. for(re int i=1;i<=n;i++)
  30. {
  31. for(re int t=1;t<=k;t++)
  32. p[now^1][t]=0;
  33. for(re int j=1;j<=k;j++)
  34. {
  35. if(j-i+1<=0) f[i][j]=(p[now][j]+mod)%mod;
  36. else f[i][j]=(p[now][j]-p[now][j-i]+mod)%mod;
  37. p[now^1][j]=(f[i][j]+p[now^1][j-1])%mod;
  38. }
  39. now^=1;
  40. }
  41. cout<<f[n][k]<<endl;
  42. return 0;
  43. }

前缀和优化dp的思想还是很重要的,以后看到这类的方程一定要往前缀和上想

【[HAOI2009]逆序对数列】的更多相关文章

  1. bzoj2431:[HAOI2009]逆序对数列

    单组数据比51nod的那道题还弱...而且连优化都不用了.. #include<cstdio> #include<cstring> #include<cctype> ...

  2. BZOJ 2431: [HAOI2009]逆序对数列( dp )

    dp(i,j)表示1~i的全部排列中逆序对数为j的个数. 从1~i-1的全部排列中加入i, 那么可以产生的逆序对数为0~i-1, 所以 dp(i,j) = Σ dp(i-1,k) (j-i+1 ≤ k ...

  3. 2431: [HAOI2009]逆序对数列

    2431: [HAOI2009]逆序对数列 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 954  Solved: 548[Submit][Status ...

  4. P2513 [HAOI2009]逆序对数列

    P2513 [HAOI2009]逆序对数列 题目描述 对于一个数列{ai},如果有iaj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数.那 ...

  5. bzoj千题计划153:bzoj2431: [HAOI2009]逆序对数列

    http://www.lydsy.com/JudgeOnline/problem.php?id=2431 dp[i][j] 表示i的排列,有j个逆序对的方案数 加入i+1,此时i+1是排列中最大的数, ...

  6. BZOJ2431 HAOI2009 逆序对数列 【DP】*

    BZOJ2431 HAOI2009 逆序对数列 Description 对于一个数列ai{a_i}ai​,如果有i<j且ai>aja_i>a_jai​>aj​,那么我们称aia ...

  7. 洛谷P2513 [HAOI2009]逆序对数列

    P2513 [HAOI2009]逆序对数列 题目描述 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的数列,可以很容易 ...

  8. bzoj2431: [HAOI2009]逆序对数列(前缀和优化dp)

    2431: [HAOI2009]逆序对数列 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 2312  Solved: 1330[Submit][Stat ...

  9. Bzoj 2431 HAOI2009 逆序对数列

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

  10. [HAOI2009]逆序对数列

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

随机推荐

  1. [转]Entity Framework Fluent API - Configuring and Mapping Properties and Types

    本文转自:https://msdn.microsoft.com/en-us/data/jj591617#1.2 When working with Entity Framework Code Firs ...

  2. PHP学习5——异常处理

    主要内容: PHP错误类型 异常的产生 错误日志 日志信息记录到操作系统日志 异常处理 扩展异常处理类 PHP错误类型 语法错误 执行时错误 逻辑错误 异常的产生 如果安装了xampp之后,在php. ...

  3. nrm的使用

    我们在开发过程中,经常会使用到 npm  install ,但是有时候npm是不稳定的,这就大大的降低了我们的开发效率.nrm正好解决了我们的这一痛点,他可以在不同的镜像之间切换,非常的方便. 一.n ...

  4. java 2018面试题-多线程汇总(含解答)

    学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行总结的,因此罗列了自己整理的多线程的问题,都是自己觉得比较经典和一些大企业面试会问 ...

  5. UVA 10328(DP,大数,至少连续)

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19825 这道题和http://www.cnblogs.com/qlky/p/ ...

  6. Redis 常见命令

    0. 5种数据类型 String(字符串) List(列表) Hash(字典) Set(集合) Sorted Set(有序集合) 1. String 字符串 set key value 设置key=v ...

  7. LeetCode Find Peak Element [TBD]

    说要写成对数时间复杂度,算了想不出来,写个O(n)的水了 class Solution { public: int findPeakElement(const vector<int> &a ...

  8. thinkphp多表联合查询

    1.两个表查询 $userid=session('user.id'); $user = M('cuser'); $data = $user->field('projectno')->whe ...

  9. android中的内部存储与外部存储

    我们先来考虑这样一个问题: 打开手机设置,选择应用管理,选择任意一个App,然后你会看到两个按钮,一个是清除缓存,另一个是清除数据,那么当我们点击清除缓存的时候清除的是哪里的数据?当我们点击清除数据的 ...

  10. python的继承多态以及异常处理

    1.单继承 # 动物类 class Animal(object): def __init__(self, name): self. __name = name def run(self): print ...