⎧⎩⎨⎪⎪big[i][j]表示子串子串[i,j]是否大于子串[i−j,j]getcnt()计数getmm()求最小值
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef __int64 LL;
const int N=5000+100;
const int mod=1e9+7;
#define lowbit(x) x&-x
const LL inf=1LL<<50;
int big[N][N];
LL sum[N],dp[N][N];
char ss[N];
int n;
void getbig(){
for(int i=1;i<=n;i++){
int pre;
for(int j=n-i+1;j>=1;j--){
int k=j-i;
if(k<1){
dp[j][i]=1;continue;
}
if(j==n-i+1){
for(pre=k;pre<j;pre++){
if(ss[pre]>ss[pre+i]){
big[j][i]=-1;break;
}
if(ss[pre]<ss[pre+i]){
big[j][i]=1;break;
}
}
if(pre==j){
big[j][i]=0;
}
continue;
}
if(ss[k]>ss[j]){
pre=k;big[j][i]=-1;
}
else if(ss[k]<ss[j]){
pre=k;big[j][i]=1;
}
else {
if(pre>=j){
pre=j;big[j][i]=0;
}
else {
big[j][i]=big[j+1][i];
}
}
}
}
}
void getcnt(){
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++){
for(int j=1;j<=n-i+1;j++){
if(ss[j]=='0')dp[j][i]=0;
else if(j>1){
if(big[j][i]>=0){
dp[j][i]=sum[j-1];
}
else dp[j][i]=(sum[j-1]-dp[j-i][i])%mod;
}
else dp[j][i]=1;
sum[j+i-1]+=dp[j][i];sum[j+i-1]%=mod;
}
}
printf("%I64d\n",(sum[n]%mod+mod)%mod);
}
void getmm(){
for(int i=1;i<=n;i++){
sum[i]=inf;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n-i+1;j++){
if(ss[j]=='0')dp[j][i]=inf;
else if(j>1){
if(big[j][i]>=0){
if(j-i>=1)dp[j][i]=min(sum[j-1],dp[j-i][i])+1;
else dp[j][i]=sum[j-1]+1;
}
else dp[j][i]=sum[j-1]+1;
}
else dp[j][i]=1;
}
for(int j=1;j<=n-i+1;j++){
sum[j+i-1]=min(sum[j+i-1],dp[j][i]);
}
}
LL ans=inf;
LL tmp=1;
LL bns=0;
for(int i=n;i>=1;i--){
bns+=tmp*(ss[i]-'0');
if(bns>ans||tmp>ans)break;
ans=min(ans,bns+dp[i][n-i+1]);
tmp*=2;
}
if(ans!=inf)printf("%I64d\n",ans%mod);
else {
bns=0;tmp=1;
for(int i=n;i>=1;i--){
bns+=tmp*(ss[i]-'0');bns%=mod;
if(dp[i][n-i+1]<=n){
//printf("%d %I64d\n",i,dp[i][n-i+1]);
printf("%I64d\n",(bns+dp[i][n-i+1])%mod);break;
}
tmp*=2;tmp%=mod;
}
}
}
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
while(scanf("%s",ss+1)!=EOF){
n=strlen(ss+1);
getbig();
getcnt();
getmm();
}
return 0;
}