首页 > 其他分享 >CF1336C(挺重要的区间dp)

CF1336C(挺重要的区间dp)

时间:2023-07-13 21:34:27浏览次数:52  
标签:const CF1336C ll int 区间 define dp MOD

Kaavi and Magic Spell - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

我们直接考虑如何构造出来的字符串,这个字符串显然只能每次最左端加或者最右端加入。

对于第一个字符,显然每个位置都够能放置,且有两种方案。接着下一个字符加入它的左端或者右端,依次类推。

令 dp[i][j] 为 s(1)~s(j-i+1) 构造出 t(i)~t(j)的方案数。

(这种思想跟合唱队是同一种区间dp思想,P3205 [HNOI2010]合唱队(区间dp+方案数) - QAQ啥也不会 - 博客园 (cnblogs.com))

 

对于dp[i][j]的转移方程:

当前s[j-i+1]加入最左边,且s[j-i+1]==t[i]:dp[i][j]=(dp[i][j]+dp[i+1][j])%MOD;

当前s[j-i+1]加入最右边,且s[j-i+1]==t[j]:dp[i][j]=(dp[i][j]+dp[i][j-1])%MOD;

 

当然显然本题 t 字符串的长度可能会短,所以 s[j-i+1] 加入的位置大于了 t 字符串的长度,显然此时一定是合法的状态

所以dp[i][j]的转移方程便是:

当前s[j-i+1]加入最左边,且s[j-i+1]==t[i] or i>tlen :dp[i][j]=(dp[i][j]+dp[i+1][j])%MOD;

当前s[j-i+1]加入最右边,且s[j-i+1]==t[j] or j>tlen :dp[i][j]=(dp[i][j]+dp[i][j-1])%MOD;

 

对于dp初始化:

for(int i=1;i<=m;i++) dp[i][i]=2*(s[1]==t[i]);

for(int i=m+1;i<=n;i++) dp[i][i]=2;

 

最后答案的统计:由于本题构造出来的字符串合法即可,所有最后的答案不是 dp[1][n],而是所有合法的dp[i][j] ,即Σdp[i][j] ( m≤j≤n )

CODE:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db long double
#define mp make_pair
#define pb push_back   
#define popb pop_back  
#define fi first
#define se second
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
const int N=3010;
//const int M=;
//const int inf=(int)1e9;
//const ll INF=(ll)1e18;
const ll MOD=998244353;
int T,n;
ll dp[N][N];
char s[N],t[N];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
int main()
{
//    freopen("","r",stdin);
//    freopen("","w",stdout);
//    ios::sync_with_stdio(0);
//    cin.tie(0);
    scanf("%s",s+1);scanf("%s",t+1);
    int n=strlen(s+1),m=strlen(t+1);
    for(int i=1;i<=m;i++) dp[i][i]=2*(s[1]==t[i]);
    for(int i=m+1;i<=n;i++) dp[i][i]=2;
    for(int len=2;len<=n;len++)
        for(int i=1;i+len-1<=n;i++)
        {
            int j=i+len-1; // dp[i][j]
            if(i>m||s[len]==t[i]) dp[i][j]=(dp[i][j]+dp[i+1][j])%MOD;
            if(j>m||s[len]==t[j]) dp[i][j]=(dp[i][j]+dp[i][j-1])%MOD;
        }
    ll ans=0;
    for(int i=m;i<=n;i++) ans=(ans+dp[1][i])%MOD;
//    for(int i=1;i<=n;i++)
//        for(int j=1;j<=n;j++)
//            printf("%d %d %d\n",i,j,dp[i][j]);
    printf("%lld\n",ans);
    return 0;
}

 

 



 

 

标签:const,CF1336C,ll,int,区间,define,dp,MOD
From: https://www.cnblogs.com/Willette/p/17552154.html

相关文章

  • ReadPaper-Pulsar Survey
    1.TheGiantMetrewaveRadioTelescope(GMRT)1,TheGMRTHighResolutionSouthernSkySurveyforPulsarsandTransients.I.SurveyDescriptionandInitialDiscoverieshttps://ui.adsabs.harvard.edu/abs/2016ApJ...817..130B/abstract2,TheGMRTHigh-resolut......
  • 动态DP
    题目链接题目大意:动态维护树上最大权独立集。所谓动态DP,就是把原先能用DP解决的问题变成动态维护DP值。如果DP数组可以支持合并两条链的话,可以直接用线段树维护,否则需要考虑把DP的转移改成矩阵,这样就可以用线段树维护矩阵,不过支持合并链以及维护矩阵都需要树链剖分,所以......
  • luogu4_dp
    背包问题、线性动归、多维动归、技巧与记忆化《背包问题九讲》背包九讲01\完全\多重\混合01(每个物品仅1个总容量V不用装满)fori=1..n forj=V..v[i] ans[j]=max(ans[j],ans[j-v[i]]+w[i]);完全(商品可多次取)fori=1..n forj=v[i]..V//区别在此 ans[......
  • 【DP】DMOPC '21 Contest 8 P5 - Tree Building
    ProblemLink给定\(n,m\)和一个长为\(m\)的代价序列,对于一棵\(n\)个节点,每个节点度数不超过\(m\)的树,定义它的代价为\(\sum\limits_{i=1}^na_{deg_i}\)。求代价最小的树的代价。\(n\le10^9,m\le3000,1\lea_i\le10^9\)。首先一眼变成选出\(n\)个\(a\)的和为......
  • 【学习笔记】插头 DP
    插头DP,是一类解决网格图上连通性问题的状压DP。相关概念轮廓线:已经决策的方格和未决策方格之间的分界线。插头:用来描述连通性,一个方格与其某一方向的相邻方格连通,则称这个方格有某个方向的插头。容易发现在轮廓线上,每个时刻都是有\(n\)个上插头与\(1\)个左插头。如图,红......
  • 动态规划DP入门笔记
    动态规划以斐波那契数列为例:\(f_i\)状态\(f_i=f_{i-1}+f_{i-2}\)转移方程\(f_0=0\),\(f_1=1\)初始化dp的实现方法一般有三种,其中的两种(最重要的)如下#include<bits/stdc++.h>usingnamespacestd;intf[200010];signedmain(){ intn; scanf("%d",&n);......
  • P1002 [NOIP2002 普及组] 过河卒 入门级别的dp
     思路:1.标记马点z[i][[j]=02.正常z[i][j]=z[i-1][j]+z[i][j-1]#include<iostream>usingnamespacestd;intn,m,a,b;longlongma[30][30],bck[30][30];intdx[8]={-2,-1,1,2,2,1,-1,-2},dy[8]={1,2,2,1,-1,-2,-2,-1};voidcan_not_reach(intx,inty){ma[......
  • 【网络面试题】你知道 TCP 和 UDP 区别吗?
    ......
  • Ubuntu资源暂时不可用 E: 无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源
    ubuntu使用apt时出现Ubuntu资源暂时不可用E:无法获得锁/var/lib/dpkg/lock-frontend-open(11:资源暂时不可用)一般是已经存在apt进程占用了,通过ps-grep查看ps-grep|apt查到相关进程后通过kill删掉kill-93298kill-93302再依次执行下面命令sudorm/var/cache......
  • RDP远程桌面凭证获取密码
    参考链接:https://blog.csdn.net/qq_36618918/article/details/130677478使用的工具:mimikatz前言该方式适用于获取系统存储的凭证中的用户名和密码,不仅限于远程桌面的凭证。使用的工具是mimikatz,杀软会报毒拦截,下载及使用的时候可以推出杀软下载地址:https://gitcode.net/mi......