1 条题解
-
0
自动搬运
来自洛谷,原作者为

TianTian2008
#85搬运于
2025-08-24 22:29:43,当前版本为作者最后更新于2024-01-08 22:25:33,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
无需多项式,直接转换一下题意然后 dp 即可。
首先可以发现拆分和字符串具体内容无关,只和 也就是 有关。
第一反应是求元素总和等于 的上升序列的数量,但观察一下样例就知道这是假的。
为什么呢?看样例, 却可以拆分成 总和为 的上升序列。观察发现,这时第二段多拿了一个 ,导致一个原本会产生贡献的 被拆开而没有产生贡献。
具体地,一个长为 的上升序列元素总和是 都是合法,因为每次拆出一个新段时都可能拆开一个 串使贡献少 。
然后就很简单了,设 表示长为 元素总和为 的上升序列的个数,显然有 。
元素总和为 的上升序列长度是 级别的,因此 dp 的时间复杂度为
注意会卡内存,滚动数组优化一下。
#include <iostream> #include <cstdio> #include <cstring> #define bas 917 #define mod 899678209 using namespace std; typedef long long ll; ll n,m,n1,n2,h1[1000010],h2,f[2][200010],ans; char str[1000010]; int main() { scanf("%s",str+1); n1=strlen(str+1); for(int i=1;i<=n1;++i) h1[i]=(h1[i-1]*bas+str[i]-'a'+1)%mod; scanf("%s",str+1); n2=strlen(str+1); ll pw=1; for(int i=1;i<=n2;++i) { h2=(h2*bas+str[i]-'a'+1)%mod; pw=pw*bas%mod; } for(int i=n2;i<=n1;++i) if(((h1[i]-h1[i-n2]*pw)%mod+mod)%mod==h2) { ++n; i+=n2-1; } ll l=1,r=n,mid; while(l<=r) { mid=l+r>>1; if((mid*(mid+1)>>1)<=n) { m=mid; l=mid+1; } else r=mid-1; } if((m*(m+1)>>1)<n) ++m; f[0][0]=1; for(int i=1;i<=m;++i) { ll x=i&1,y=x^1; for(int j=0;j<=n;++j) if(i>j) f[x][j]=0; else { f[x][j]=f[y][j-i]+f[x][j-i]; if(f[x][j]>=mod) f[x][j]-=mod; } if(i==1) continue; for(int j=n-i+1;j<=n;++j) { ans+=f[x][j]; if(ans>=mod) ans-=mod; } } printf("%lld",ans); return 0; }
- 1
信息
- ID
- 6452
- 时间
- 1000ms
- 内存
- 64~256MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者