zoukankan      html  css  js  c++  java
  • 【vijos】1757 逆序对(dp)

    https://vijos.org/p/1757

    有时候自己sb真的是不好说。。。

    我竟然想了半天都没想到这个转移。

    我是有多傻。。。。

    我们设f[i][j]表示1~i的排列且逆序对恰好是j的方案数。

    显然我们只需要将i放进i-1排列中就行了。

    而且发现i始终大于i-1

    那么就好做了,我们只要将所有i放到i-1序列的位置的方案全都加起来即可,即:

    f[i][j]=sum{f[i-1][k], max{0, j-i+1}<=k<=j}

    用前缀和搞搞就行了。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
    #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=1005, MD=10000;
    int f[N], sum[N], n, k;
    
    int main() {
    	int cs=getint();
    	while(cs--) {
    		CC(f, 0); CC(sum, 0);
    		f[0]=1;
    		read(n); read(k);
    		for1(i, 1, n) {
    			for1(j, 1, k+1) sum[j]=sum[j-1]+f[j-1], sum[j]%=MD;
    			for1(j, 0, k) f[j]=(sum[j+1]-sum[max(0, j-i+1)]+MD)%MD;
    		}
    		printf("%d
    ", f[k]);
    	}
    	return 0;
    }
    

      


    描述

    对于1-n的任意一个排列:a1,a2,a3...an,如果存在i<j,且ai>aj,则(i,j)称之为一对逆序对。

    我们常常关心一个排列的逆序对的总数,因为它可以反映一个排列的有序程度。

    现在小D想知道,在1-n的所有排列中,有多少排列的逆序对总数恰好为k。

    格式

    输入格式

    第一行为正整数T,表示数据组数
    接下来T行,每行两个正整数:n,k

    输出格式

    对于每个输入,输出一行表示恰好为k的排列的个数。由于数字可能较大,只需要输出mod10000的结果即可。

    样例1

    样例输入1[复制]

     
    1
    4 1

    样例输出1[复制]

     
    3

    限制

    每个测试点1s

    提示

    对于样例的解释,下面的排列满足条件:
    1 2 4 3
    1 3 2 4
    2 1 3 4

    对于30%的数据 n<=12;
    对于100%的数据 n<=1000,k<=1000,T<=10;

  • 相关阅读:
    二分查找:思路很简单,细节是魔鬼
    今天遇到了 X-Y PROBLEM
    《工匠精神》读书笔记
    养成好的职业习惯
    php xdebug 调试
    Dockerfile的常见命令
    docker制作镜像
    脱坑笔记
    Java中代理
    2、遇到多个构造器参数的时候要考虑使用构建器
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4023583.html
Copyright © 2011-2022 走看看