HDU 6348 序列计数(2018百度之星资格赛04,dp+树状数组)

版权声明:本文为博主原创文章,转载请注明出处,欢迎转载。 https://blog.csdn.net/Dylan_Frank/article/details/81610427

题目链接

序列计数

给定一个 n 排列,求长度为 l 的排列总数( l = 1 , 2 , 3 , n )

分析

这里写图片描述

code

#include <bits/stdc++.h>
using namespace std;

#define MAXN    (10009)
#define MOD     1000000007
#define ms(x,v) memset((x),(v),sizeof((x)))
#define INF     0x3f3f3f3f
#define pb      push_back
#define fi      first
#define se      second
#define mp      make_pair

typedef unsigned long long      uLL;
typedef long long               LL;
typedef pair<int,int >          Pair;

/*****  field ****/

LL dp[2][MAXN];
LL ans[MAXN];
LL tree[MAXN];//树状数组
int n;
int p[MAXN];
/********function *********/

/*****树状数组****/

void add(int idx,int val){
    if(val==0)return;
    while (idx < MAXN) {
        tree[idx] += val;
        idx += (-idx &idx);
    }
}
LL sum(int idx){
    LL ret = 0;
    while (idx >0) {
        ret += tree[idx];
        idx -= (-idx & idx);
    }
    return ret%MOD;
}
int main(int argc, char const *argv[]) {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int T;
    cin >> T;
    ms(dp,0);
    for(int _=1 ; _<=T ; ++_) {
        cin >> n;
        for(int i=1 ; i<= n ; ++i)cin >> p[i];
        ms(ans,0);
        ans[1] = n;
        for(int i=1 ; i <=n ; ++i)dp[0][i] =1;
        int t = 0;

        for(int l = 2 ; ; ++l){
            t^=1;
            ms(tree,0);
            for(int i = 1 ; i <= n ; ++i){
                LL tmp = sum(p[i]-1);
                ans[l] = (ans[l] + tmp) % MOD;
                dp[t][i] = tmp;
                add(p[i],dp[t^1][i]);
            }
            if(ans[l] ==0)break;
        }
        std::cout << "Case #"<<_ << ":";
        for(int i=1; i<=n ; ++i)std::cout << " "<<ans[i] ;std::cout  << '\n';
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dylan_Frank/article/details/81610427