1. 程式人生 > 實用技巧 >T - Permutation 題解(思維+dp)

T - Permutation 題解(思維+dp)

題目連結

題目大意

給你一個數字n和長為n-1個字串

字串包含'<','>'

若s[i]='<' 則代表a[i]<a[i+1]

若s[i]='>' 則代表a[i]>a[i+1]

你要構造一個長度為n的全排列,使其滿足條件

求方案數mod 1e9+7

題目思路

這個問題主要就是不知道如何保證自己構造的陣列是一個全排列

又是一個神仙dp,

\(dp[i][j]\)代表[1,i]為全排列,且第i個元素為j

那麼該怎麼轉移。

若為'<' \(dp[i][j]=\sum_{t=1}^{t=j-1} dp[i-1][t]\)

若為‘>’ \(dp[i][j]=\sum_{t=j}^{t=n} dp[i-1][t]\)

這個轉移實屬神奇,把j放到i-1個全排列後面,然後前i-1中大於等於j的元素全部加1即可

這樣前i個元素又滿足全排列,最後一個元素還是j,滿足轉移方程

然後字首和優化即可,注意j<=i

程式碼

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define debug printf(" I am here\n");
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=3e3+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-10;
int n,flag[maxn];
char s[maxn];
ll dp[maxn][maxn],pre[maxn][maxn];
int main(){
    scanf("%d %s",&n,s+1);
    for(int i=1;i<=n-1;i++){
        if(s[i]=='<'){
            flag[i]=1;
        }else{
            flag[i]=0;
        }
    }
    dp[1][1]=1;
    for(int i=1;i<=n;i++){
        pre[1][i]=1;
    }
    for(int i=2;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(j>i){
                pre[i][j]=pre[i][j-1];
                continue;
            }
            if(flag[i-1]){
                dp[i][j]=pre[i-1][j-1]%mod;
            }else{
                dp[i][j]=((pre[i-1][n]-pre[i-1][j-1])%mod+mod)%mod;
            }
            pre[i][j]=(pre[i][j-1]+dp[i][j])%mod;
        }
    }
    printf("%lld\n",pre[n][n]);
    return 0;
}