[NOIP模拟][dp][codevs]p1401逆序对统计

7 篇文章 0 订阅
4 篇文章 0 订阅
题目描述 Description

       我们说(i,j)是a1,a2,…,an的一个逆序对当且仅当i<j且ai>aj。例如2,4,1,3,5的逆序对有3个,分别为(1,3),(2,3),(2,4)。现在已知N和K,求1..N的所有特定排列,这些排列的逆序对的数量恰好为K。输出这些特定排列的数量。

       例如N=5,K=3的时候,满足条件的排列有15个,它们是:

1,2,5,4,3   1,3,4,5,2    1,3,5,2,4     1,4,2,5,3   1,4,3,2,5

1,5,2,3,4   2,1,4,5,3    2,1,5,3,4     2,3,1,5,4   2,3,4,1,5

2,4,1,3,5   3,1,2,5,4    3,1,4,2,5     3,2,1,4,5   4,1,2,3,5

输入描述 Input Description

输入第一行有两个整数N和K。其中(N<=100,K<=N*(N-1)/2)


输出描述 Output Description

将1..N的逆序对数量为K的特定排列的数量输出,为了避免高精度计算,请将结果mod10000后再输出

样例输入 Sample Input

【样例输入1】

5 3

 

【样例输入2】

10 7

 

【样例输入3】

10 10

样例输出 Sample Output

【样例输出1】

15

 

【样例输出2】

4489

 

【样例输出3】

1670

方程很容易得出:f[i][j]=f[i-1][j-i+1]+f[i-1][j-i+2]+……+f[i-1][j]

但是若果这样是O(n^3)

可以优化为O(n^2)

f[i][j]=f[i-1][j-i+1]+f[i-1][j-i+2]+……+f[i-1][j]

f[i][j-1]=f[i-1][j-i]+f[i-1][j-i+1]+f[i-][j-i+2]+……+f[i-1][j-1]

这两个式子有许多重复项

所以可以合并为f[i][j]=f[i][j-1]+f[i-1][j]-f[i-1][j-i]

代码:

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
#define INF 0x3f3f3f3f
#define clock CLOCKS_PER_SEC
#define cle(x) memset(x,0,sizeof(x))
#define maxcle(x) memset(x,127,sizeof(x))
#define mincle(x) memset(x,-1,sizeof(x))
#define cop(a,x) memcpy(x,a,sizeof(a))
#define FROP "codvs"
#define C(a,b) next_permutation(a,b)
#define LL long long
using namespace std;
const int N=105,mod=1e4;
int n,k,f[N*N/2][N];
int main()
{
freopen(FROP".in","r",stdin);
freopen(FROP".out","w",stdout);
scanf("%d%d",&n,&k);
for(int i = 0 ; i <= n; i++)
f[0][i]=1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= k; j++)
{
f[j][i]=(f[j][i-1]+f[j-1][i])%mod;
if(j>=i)f[j][i]=(f[j][i]-f[j-i][i-1]+mod)%mod;//!!!!!!!1减后防止为负数,,而且j>=i!!!!!!
}
printf("%d",f[k][n]);
return 0;
}

还有两点很重要

1.j>=i,,数组下标运算时,不能为负数。。。!!!!!!!!注意判断,,,这个递推式子。。

2.当要模一个数的时候,,,特别当有减的时候,,一定要加上这个数在减去在模,防止模后又减去未负数!!!!!!!!!

if(j>=i)f[j][i]=(f[j][i]-f[j-i][i-1]+mod)%mod;///!!!!!!!!!!!!!!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值