Double Strings
Double Strings
題意:
給你s和t兩個(gè)字符串,在其中選出兩個(gè)等長(zhǎng)的子序列(可以不連續(xù))a,b,滿足a的字典序嚴(yán)格小于b的字典序,問(wèn)方案數(shù),答案mod(1e9+7)
題解:
好的方案的構(gòu)成是一段相同的前綴+一個(gè)不同的字符(a比b小)+長(zhǎng)度相同的任意后綴,按照這樣構(gòu)造一定是合法且包含所有情況
我們用dp[i][j]表示只考慮A的前i個(gè)字符和B的前j個(gè)字符時(shí)的相同的子序列的個(gè)數(shù)(有點(diǎn)類似于最長(zhǎng)公共子序列,不過(guò)我們這里記錄的是方案數(shù))
轉(zhuǎn)移方程可得:dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1](加上之前的情況減去重復(fù)的)
當(dāng)a[i]=b[j]時(shí),dp[i][j]=dp[i-1][j-1]+1
現(xiàn)在是如何求長(zhǎng)度相同的任意后綴,我們假設(shè)A中剩余長(zhǎng)度是x,B中剩余長(zhǎng)度位y,設(shè)x<=y,那么求長(zhǎng)度相同的任意后綴,就是A和B中分別取i個(gè)(i最大到x),有:∑i=0xCxiCyi=∑i=0xCxx?iCyi=Cx+yx\sum_{i=0}^{x}C_{x}^{i}C_{y}^{i}=\sum_{i=0}^{x}C_{x}^{x-i}C_{y}^{i}=C_{x+y}^{x}∑i=0x?Cxi?Cyi?=∑i=0x?Cxx?i?Cyi?=Cx+yx?
每步推導(dǎo)過(guò)程都是用的常規(guī)組合數(shù)公式變換
代碼:
#include<bits/stdc++.h> #define debug(a,b) printf("%s = %d\n",a,b); using namespace std; typedef long long ll; typedef pair<int, int> PII; //Fe~Jozky const ll INF_ll=1e18; const int INF_int=0x3f3f3f3f; inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; } void rd_txt(){#ifdef ONLINE_JUDGE#elsefreopen("in.txt","r",stdin);#endif } const int maxn=1e6+9; const int mod=1e9+7; ll fac[maxn]; ll inv[maxn]; ll dp[6000][6000]; char s[maxn],t[maxn]; int C(int n,int m) {if(n<m) {return 0;}return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod; } ll poww(ll a,ll b){ll ans=1;while(b){if(b&1){ans=ans*a%mod;}a=a*a%mod;b>>=1;}return ans; } void init() {fac[0]=1;int N=1e6;for(int i=1;i<=N;i++) {fac[i]=1LL*fac[i-1]*i%mod;}inv[N-1]=poww(fac[N-1],mod-2);for(int i=N-2;i>=0;i--) {inv[i]=1LL*inv[i+1]*(i+1)%mod;} } int main() {init();scanf("%s%s",s+1,t+1);int n=strlen(s+1),m=strlen(t+1);for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {dp[i][j]=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1])%mod;if(s[i]==t[j]) {dp[i][j]=(dp[i][j]+dp[i-1][j-1]+1)%mod;}dp[i][j]=(dp[i][j]+mod)%mod;}}ll ans=0;for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {if(s[i]<t[j]) {ans=(ans+1LL*(dp[i-1][j-1]+1)*C(n-i+m-j,n-i))%mod;}}}cout<<ans<<endl;return 0; }總結(jié)
以上是生活随笔為你收集整理的Double Strings的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何去视频水印轻抖如何去视频水印
- 下一篇: P3567 [POI2014]KUR-C