[CF1051E Vasya and Big Integers](Problem - E - Codeforces)

sb的做法

单调队列乱整(

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5,MOD=998244353;
int n,len1,len2;
string s,l,r;
int q[N],st=1,ed,us=1;
bool ck_l(string t){
if(t.size()<l.size()) return true;
if(t.size()>l.size()) return false;
return t<l;
}
bool ck_r(string t){
if(t.size()<r.size()) return false;
if(t.size()>r.size()) return true;
return t>r;
}
bool check(int st,int ed){
string t=s.substr(st,ed-st+1);
// cout<<st<<" "<<ed<<" "<<t<<" "<<((t<l)?1:0)<<" "<<((t>r)?1:0)<<" "<<((t[0]=='0')?1:0)<<endl;
return ck_l(t)||ck_r(t)||(t[0]=='0'&&st!=ed);
}
ll dp[N],sum=1;
int main(){
char t;
cin>>s,cin>>l,cin>>r;
// cout<<"\n-------"<<r<<"------"<<endl;
s='#'+s;
n=s.size()-1,dp[0]=1;
for(int i=1;i<=n;++i){
q[++ed]=i;
while(st<=ed&&check(q[st],i)) (sum+=-dp[q[st]-1]+MOD)%=MOD,++st;
if(st>ed) return printf("0"),0;
while(us<ed&&us<st) ++us,(sum+=dp[q[us]-1])%=MOD;
while(us+1<=ed&&!check(q[us+1],i)) ++us,(sum+=dp[q[us]-1])%=MOD; dp[i]=sum;
// cout<<i<<" "<<st<<" "<<us<<" "<<ed<<" "<<dp[i]<<endl;
}
printf("%lld\n",dp[n]);
return 0;
}

大概思路:

用一个单调队列来维护当前可以选择用来当最后一段的开头的所有下标

然后因为新加的点不一定能马上用到(因为有下限),所以除了sted外还有us

区间[st,us]就是可以用的下标

不过这是戳的,下辈子有空再弄吧。。。

正解

算出slr的\(extend\),然后就可以进行\(DP\)了

在\(DP\)中,算出可以转移到i的下标取值范围\([l1,r1]\)

可以先得出一个大概的范围:\([i+len_l-1,i+len_r-1]\),因为当前划分出来的字符串的长度的范围为[len1,len2]

倒着\(DP\),\(dp[i]\)表示以i开头有多少种划分方式

然后如果\(s\)与\(l\)不相等的第一个位置上,\(l\)较大,则说明当前划分出来的字符串的长度至少为\(len_l+1\);如果\(s\)与\(l\)不相等的第一个位置上,\(r\)较小,则说明当前划分出来的字符串的长度最大为\(len_r-1\)

然后前缀和优化,这道题就G了

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5,MOD=998244353;
int n,len1,len2,nxt1[N],nxt2[N],extend1[N],extend2[N];
char s[N],l[N],r[N];
void exkmp(char s[],int n,int nxt[]){
nxt[1]=n;
for(int i=2,a=0,p=0;i<=n;++i){
if(i<p) nxt[i]=min(nxt[i-a+1],p-i);
while(i+nxt[i]<=n&&s[nxt[i]+1]==s[i+nxt[i]]) ++nxt[i];
if(i+nxt[i]>p) p=i+nxt[i],a=i;
}
}
void ekp(char s[],char t[],int n,int m,int nxt[],int extend[]){
for(int i=1,a=0,p=0;i<=n;++i){
if(i<p) extend[i]=min(nxt[i-a+1],p-i);
while(i+extend[i]<=n&&extend[i]+1<=m&&s[i+extend[i]]==t[extend[i]+1]) ++extend[i];
if(i+extend[i]>p) p=i+extend[i],a=i;
}
}
ll dp[N],sum[N];
int main(){
scanf("%s\n%s\n%s",s+1,l+1,r+1);
n=strlen(s+1),len1=strlen(l+1),len2=strlen(r+1);
exkmp(l,len1,nxt1),exkmp(r,len2,nxt2);
ekp(s,l,n,len1,nxt1,extend1),ekp(s,r,n,len2,nxt2,extend2);
sum[n+1]=dp[n+1]=1;
for(int i=n;i;--i){
if(s[i]=='0') dp[i]=(l[1]=='0')*dp[i+1];
else{
int l1=i+len1-1,r1=i+len2-1;
if(extend1[i]<len1&&l[extend1[i]+1]>s[i+extend1[i]]) ++l1;
if(extend2[i]<len2&&r[extend2[i]+1]<s[i+extend2[i]]) --r1;
r1=min(r1,n);
if(l1>r1) dp[i]=0;
else dp[i]=((sum[l1+1]-sum[r1+2])%MOD+MOD)%MOD;
}
sum[i]=(dp[i]+sum[i+1])%MOD;
}
printf("%lld",dp[1]);
return 0;
}

最新文章

  1. 使用C#类向数据库添加数据的例子源码
  2. Xcode插件优缺点对比(推荐20款插件)
  3. ASP.NET Core和Angular 2双剑合璧
  4. mac os 中类似于Linux的yum工具,或ubuntu的apt-get工具Homebrew
  5. HDU 1069 Monkey and Banana(二维偏序LIS的应用)
  6. oracle稳定执行计划1
  7. RedHat7 SELinux
  8. WPF DataGrid某列使用多绑定后该列排序失效,列上加入 SortMemberPath 设置即可.
  9. Qt入门学习——Qt 5 帮助文档的使用
  10. zookeeper基本讲解及基本命令和配置 (转)
  11. LeetCode(35)-Path Sum
  12. Tomcat中文乱码解决办法
  13. Tomcat的配置文件详解
  14. linux 同步IO: sync、fsync与fdatasync、sys_sync【转】
  15. Oracle错误——SP2-0734: 未知的命令开头 &quot;imp C##sin...&quot; - 忽略了剩余的行。
  16. Ng第三课:线性代数回顾(Linear Algebra Review)
  17. kubernetes集群部署mysql 8.0
  18. Android之AlarmManager
  19. laravel 控制器中使用 try catch
  20. BZOJ2208:[JSOI2010]连通数——题解

热门文章

  1. 深度优先搜索(Depth-First-Search)dfs代码模板
  2. 死磕面试系列,Java到底是值传递还是引用传递?
  3. xamarin.Android自动升级
  4. [论文阅读] 颜色迁移-N维pdf迁移
  5. 1. PyQt5开发环境的搭建
  6. [.NET学习] EFCore学习之旅 -1
  7. [奶奶看了都会]ChatGPT保姆级注册教程
  8. Python报AttributeError: module &#39;string&#39; has no attribute &#39;join&#39;解决方法
  9. Anaconda下载安装
  10. Pytorch 基本操作