bzoj2431

题意:求有多少个逆序对为k的排列
题解:\(dp[i][j]\)表示1i的排列中有j个逆序对的方案数,转移就是把i放在1i-1的排列中的第几位,\(dp[i][j]=\sum_{x=0}^{min(i-1,j)}dp[i-1][j-x]\),前缀和随便优化下就O(n^2)了

/**************************************************************
    Problem: 2431
    User: walfy
    Language: C++
    Result: Accepted
    Time:68 ms
    Memory:1312 kb
****************************************************************/
 
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
//#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define ull unsigned long long
//#define base 1000000000000000000
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}
 
using namespace std;
 
const ull ba=233;
const db eps=1e-7;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=1000+10,maxn=1000000+10,inf=0x3f3f3f3f;
 
ll dp[2][N],sum[N];
int main()
{
    int n,k;scanf("%d%d",&n,&k);
    int now=0,pre=1;
    dp[now][0]=1;
    for(int i=0;i<=k;i++)sum[i]=1;
    for(int i=2;i<=n;i++)
    {
        swap(now,pre);
        memset(dp[now],0,sizeof dp[now]);
        for(int j=0;j<=k;j++)
        {
            if(j==min(i-1,j))dp[now][j]=sum[j];
            else dp[now][j]=(sum[j]-sum[j-min(i-1,j)-1]+10000)%10000;
        }
        sum[0]=dp[now][0];
        for(int j=1;j<=k;j++)sum[j]=(sum[j-1]+dp[now][j])%10000;
    }
    printf("%lld\n",dp[now][k]);
    return 0;
}
/********************
 
********************/
posted @ 2019-02-26 19:55  walfy  阅读(194)  评论(0编辑  收藏  举报