每個點有向左,向右,都可以,三種跳躍屬性。問從起點到終點的,經過每個點一次的方案數。
我們要求的就是合法的全排列,滿足起點是第一個,終點是最後一個,任何一個可以到下一個的數量。
我們考慮最後的這個排列,從1開始,對每個數考慮其應該放在哪裏。
我們發現,任何時刻,這樣放出來的連通塊,右端點一定是R或B,左端點一定是L或B。
因爲我們從1~n添加,所以沒有添加的數一定比添加了的數大。如果是右端點,就要到達一個比自己大的,那我只能向右。
反之就是向左。
然後我們發現,要產生這樣的限制,只能說明我跟連通塊發生了關係(或者自己成了一個新連通塊)
所以可以設置狀態f[i][j]表示考慮到數i,現在有j個連通塊的方案數。
但是我們發現,起點和終點的位置是確定的,要提出來討論。所以我們設free爲不是起點,終點的連通塊數量。
所以狀態轉移是這樣的:
如果i+1是起點:
其要麼自成一個新連通塊,要麼和一個普通連通塊連在一起。
如果i+1是終點:
其要麼自成一個新連通塊,要麼和一個前面的普通連在一起。
如果都不是:
1:自成一個連通塊
2。和起點連通塊連接。
3。和起點連通塊以及一個普通連通塊連接。
4。和終點連接。
5。和終點連通塊以及一個普通連通塊連接。
6。成爲一個普通塊的右端點。
7。成爲一個普通塊的左端點。
8。連接兩個普通聯通塊。
然後就寫吧,,
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define int long long
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;
ch=getchar();
}return cnt*f;
}
const int mod=1e9+7;
int f[5003][5003];
char ch[5003],n,s,e;
signed main(){
scanf("%s",ch+1);
n=strlen(ch+1);s=in;e=in;
f[0][0]=1;
for(int i=0;i<=n-2;i++){
int st;if(i==0)st=0;else st=1;
for(int j=st;j<=i;j++){
long long key=f[i][j];if(!key)continue;
int free=j;
if(i>=s)free--;if(i>=e)free--;if(free<0)continue;char x=ch[i+1];
if(i+1==s){
if(x=='R'||x=='B')f[i+1][j+1]=(f[i+1][j+1]+key)%mod;
if(x=='L'||x=='B')f[i+1][j]=(f[i+1][j]+key*free)%mod;
}
else if(i+1==e){
f[i+1][j+1]=(f[i+1][j+1]+key)%mod;
f[i+1][j]=(f[i+1][j]+key*free)%mod;
}
else{
if(x=='R'||x=='B')f[i+1][j+1]=(f[i+1][j+1]+key)%mod;
if(i+1>s&&(x=='R'||x=='B'))f[i+1][j]=(f[i+1][j]+key)%mod;
if(i+1>s&&(x=='L'||x=='B')&&j)f[i+1][j-1]=(f[i+1][j-1]+key*free)%mod;
if(i+1>e&&(x=='L'||x=='B'))f[i+1][j]=(f[i+1][j]+key)%mod;
if(i+1>e&&(x=='L'||x=='B')&&j)f[i+1][j-1]=(f[i+1][j-1]+key*free)%mod;
if(x=='R'||x=='B')f[i+1][j]=(f[i+1][j]+free*key)%mod;
if(x=='L'||x=='B')f[i+1][j]=(f[i+1][j]+free*key)%mod;
if(free>=2&&(x=='L'||x=='B'))f[i+1][j-1]=(f[i+1][j-1]+key*free%mod*(free-1)%mod)%mod;
}
}
}int ans=0;
if(n==s){if(ch[n]=='L'||ch[n]=='B')ans=f[n-1][1];}
else if(n==e)ans=f[n-1][1];
else if(ch[n]=='L'||ch[n]=='B')ans=f[n-1][2];
cout<<ans;
return 0;
}