BZOJ 2431 & DP

题意:求逆序对数量为k的长度为n的排列的个数

SOL:

  显然我们可以对最后一位数字进行讨论,判断其已经产生多少逆序对数量,然后对于前n-1位同样考虑---->每一个长度的排列我们都可以看做是相同的,因为它与最后一位的影响我们已经计算过了.那么就变成了一个好多维DP的过程...

  不过我的方程感觉有点太直白,应该可以优化因为在BZ上都是卡时过去的...太慢了...大概状态还是有问题....

Code:  

/*=================================================================
# Created time: 2016-03-30 19:36
# Filename: 2431.cpp
# Description:
=================================================================*/
#define me AcrossTheSky
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> 

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector> 

#define lowbit(x) (x)&(-x)
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)
#define ls(a,b) (((a)+(b)) << 1)
#define rs(a,b) (((a)+(b)) >> 1)
#define getlc(a) ch[(a)][0]
#define getrc(a) ch[(a)][1] 

#define mod 10000
#define maxn 1100
#define maxk 1010
#define maxm 100000
#define pi 3.1415926535898
#define _e 2.718281828459
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 

template<class T> inline
void read(T& num) {
    bool start=false,neg=false;
    char c;
    num=0;
    while((c=getchar())!=EOF) {
        if(c==‘-‘) start=neg=true;
        else if(c>=‘0‘ && c<=‘9‘) {
            start=true;
            num=num*10+c-‘0‘;
        } else if(start) break;
    }
    if(neg) num=-num;
}
/*==================split line==================*/
int f[maxn][maxk];
int main(){
	int n,k;
	read(n); read(k);
	memset(f,0,sizeof(f));
	f[1][0]=1;
	FORP(i,1,n)
		FORP(j,1,i) {
			int t=i-j;
			FORP(l,0,k-t)
				f[i][l+t]+=f[i-1][l],f[i][l+t]%=mod;
		}
	printf("%d\n",f[n][k]);
}
时间: 2024-11-08 05:59:55

BZOJ 2431 & DP的相关文章

bzoj 1791 DP

首先对于一棵树我们可以tree_dp来解决这个问题,那么对于环上每个点为根的树我们可以求出这个树的一端为根的最长链,并且在tree_dp的过程中更新答案.那么我们对于环,从某个点断开,破环为链,然后再用DP来解决这个问题. 备注:很久之前的一道题,刚转的c++,然后T了,也懒得改了. /************************************************************** Problem: 1791 User: BLADEVIL Language: C++

bzoj 1222 DP

用w[i]表示在A中用了i的时间时在B中最少用多长时间,然后转移就可以了. 备注:这个边界不好定义,所以可以每次用一个cur来存储最优值,然后对w[i]赋值就可以了. /************************************************************** Problem: 1222 User: BLADEVIL Language: C++ Result: Accepted Time:2648 ms Memory:992 kb ***************

bzoj 3622 DP + 容斥

LINK 题意:给出n,k,有a,b两种值,a和b间互相配对,求$a>b$的配对组数-b>a的配对组数恰好等于k的情况有多少种. 思路:粗看会想这是道容斥组合题,但关键在于如何得到每个a[i]大于b的组数. 不妨从整体去考虑,使用$f[n][j]$代表前n个中有j组$a[i]>b[i]$,很容易得到转移式$f[n][j]=f[n-1][j]+f[n-1][j-1]*(cnt[n]-(j-1))$,其中$cnt[i]$为比a[i]小的b[]个数 但是仔细思考该式子含义会发现,$f[n][j

BZOJ 2431: [HAOI2009]逆序对数列【dp】

Description 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数.那么逆序对数为k的这样自然数数列到底有多少个? Input 第一行为两个整数n,k. Output 写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果.   Sample Input样例输入 4 1 Sample Output样例输出 3 样例说明: 下列3个数列逆序对

bzoj 2431: [HAOI2009]逆序对数列

一个比较弱智的DP 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #include<vector> 9 #define M 1009 10 #define EPS 1e-10 11

[bzoj 2431][HAOI2009]逆序对数列(递推+连续和优化)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2431 分析: f(i,j)表示前i个数字逆序对数目为j时候的方案数 那么有f(i,j)=∑f(i-1,k)  j-i+1<=k<=j 看似是n*k*k的,但是注意对于每一个i,当j=j+1时候,结果只是f(i,j)基础上加了一个f(i-1,j+1),所以就是n*k的了

BZOJ 2101 DP+优化

思路: http://www.cnblogs.com/exponent/archive/2011/08/14/2137849.html f[i,i+len]=sum[i,i+len]-min(f[i+1,i+len],f[i,i+len-1]); 但题目把n出到5000,内存卡到64M,二维的状态存不下.. 其实,j这一维可以省掉.我们换个状态表示 f[i,i+len]=sum[i,i+len]-min(f[i+1,i+len],f[i,i+len-1]) 然后循环这样写: for len=1

BZOJ 1003 dp+最短路

1003: [ZJOI2006]物流运输 题意:m个码头,从码头1到码头m,连续n天都要运送货物.每一天的花费是总路线长度大小,但如果和前一天的路线不一样,要另处加上k元花费.而且有些码头有些天不能用,问这n天的最小费用. tags:菜鸡一开始真没想到是dp 求n天时最小花费,就要想到以天数为阶段进行规划.dp[i][j]表示第i天到第j天走同一条路线的花费,则f[i]=min( f[i], f[j]+dp[j+1][i]+k ). #include<bits/stdc++.h> using

bzoj 1009 DP 矩阵优化

原来的DP: dp[i][j]表示长度为i的合法串,并且它的长度为j的后缀是给定串的长度为j的前缀. 转移: i==0 dp[0][0] = 1 dp[0][1~m-1] = 0 i>=1 dp[i][0] = dp[i-1][0]*10-dp[i-1][m-1] dp[i][1] = dp[i-1][0]-(a[m]==a[1])*dp[i-1][m-1] dp[i][2] = dp[i-1][1]-(a[m-1~m]==a[1~2])*dp[i-1][m-1] dp[i][3] = dp[i