诸城模拟赛 dvd的逆序对

【题目描述】

dvd是一个爱序列的孩子。

他对序列的热爱以至于他每天都在和序列度过

但是有一个问题他却一直没能解决

给你n,k1~n有多少排列有恰好k个逆序对

【输入格式】

一行两个整数n,k

【输出格式】

输出一个整数,表示答案对1000000007取模后的结果

【样例输入】

 4 1

【样例输出】

3

【样例解释】

1 2 4 3

1 3 2 4

2 1 3 4

【数据规模及约定】

对于10%的数据  n<=10

对于30%的数据  k<=50

对于100%的数据 1<=n,k<=1000 k<=n*(n-1)/2

 

/*
当年的爆零题,今年的一眼题
我们可以注意到,题目中要求的是这个方案数,而且这个数字很大,要对一个很大的数取模,考虑dp,f[i][j]表示1~j的排列恰好有i个逆序对,考虑f[i][j+1],等于是多了一个数字j+1,包括这个数字的逆序对是他后面的数的个数,剩下的逆序对就又前面j的排列来填补,这样维护一个前缀和,f[i][j] = f[i-j+1……i][j-1]
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1050;
const int mod = 1000000007;
int n,k,f[maxn][maxn],s[maxn][maxn];
int main(){
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    cin>>n>>k;
    for(int i = 1;i <= n;i++) s[0][i] = f[0][i] = 1;
    for(int i = 1;i <= k;i++){
        for(int j = 1;j <= n;j++){
            if(i >= j)f[i][j] = (s[i][j-1] - s[i-j][j-1] + mod) % mod;
            else f[i][j] = s[i][j-1];
            s[i][j] = (s[i-1][j] + f[i][j]) % mod;
        }
    }
    cout<<f[k][n]<<endl;
    return 0;
}

 

 

 

posted @ 2016-10-06 23:14  ACforever  阅读(172)  评论(0编辑  收藏  举报