题目描述

题解

过于真实

LJ卡常题

一个显然的dp:

设f[i][j]表示做完前i个,最后一段为j+1~i的方案(最小值同理)

那么f[i][j]=min(f[i-j-1][k]),其中k~j-1要小于j~i

这样做是n3的,而且不好判断二进制的大小

一个很显然的想法,把所有的状态丢到trie上转移,先按位数(深度),再按字典序(先0后1)来转移

每次维护f[i],表示当前以i结尾的方案,那么对于当前的f[i]加上f[i-长度]

因为连续多段相同的数,所以trie上每个点挂的状态要从小到大排(即反着加邻接表)

可以发现这样的实质是把所有状态按字典序转移,而且对于每个i和j,每个k只会被加一次


一些小(?)优化:

每个段的结尾的下一位必须要是1,不然没法往下接

f[i][j]如果j<n,那么要保证j-i+1≤n-j


trie的大小是n2的(每个后缀),状态总数也是n2,所以理论复杂度是O(n^2)

加上上面的优化,在正常的评测机上跑不会有什么问题

然而——

由于51nod的神奇评测机,在本地&jzoj上跑1.1s(加了O2跑1.2s别问为什么变慢了),在51nod上跑了1.6s+

所以

你懂得

code

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <bitset>
#define fo(a,b,c) for (register int a=b; a<=c; a++)
#define fd(a,b,c) for (register int a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define mod 1000000007
#define LEN 12502500
using namespace std; char St[5002]={"你懂得"};
struct type{
short int a[5003];
int len;
} ans,a1,a2;
short int A[LEN+1];
int B[LEN+1];
int ls[LEN+1];
int tr[LEN+1][2];
int a[5001];
int d[2][5001];
int f[5001];
int g[5001];
int t[2];
int I,I2,n,i,j,k,l,sum,len,L,Ans;
char ch;
bool bz; void add()
{
register int i; if (a1.len>=a2.len)
{
a1.a[a1.len+1]=0;
bz=0; fo(i,1,a2.len)
{
a1.a[i]+=a2.a[i]; if (a1.a[i]>1)
{
a1.a[i]-=2;
++a1.a[i+1];
}
}
fo(i,a2.len+1,a1.len)
if (a1.a[i]>1)
{
a1.a[i]-=2;
++a1.a[i+1];
}
else
break; if (a1.a[a1.len+1])
++a1.len;
}
else
{
a2.a[a2.len+1]=0;
bz=1; fo(i,1,a1.len)
{
a2.a[i]+=a1.a[i]; if (a2.a[i]>1)
{
a2.a[i]-=2;
++a2.a[i+1];
}
}
fo(i,a1.len+1,a2.len)
if (a2.a[i]>1)
{
a2.a[i]-=2;
++a2.a[i+1];
}
else
break; if (a2.a[a2.len+1])
++a2.len;
}
} void cmp()
{
register int i; if (!bz)
{
if (ans.len>a1.len)
ans=a1;
else
if (ans.len==a1.len)
{
fd(i,ans.len,1)
if (ans.a[i]>a1.a[i])
{
ans=a1;
return;
}
else
if (ans.a[i]<a1.a[i])
return;
}
}
else
{
if (ans.len>a2.len)
ans=a2;
else
if (ans.len==a2.len)
{
fd(i,ans.len,1)
if (ans.a[i]>a2.a[i])
{
ans=a2;
return;
}
else
if (ans.a[i]<a2.a[i])
return;
}
}
} void turn(register int t)
{
while (t)
{
a2.a[++a2.len]=t&1;
t>>=1;
}
} int main()
{
// freopen("51nod_1790_35_in.txt","r",stdin);
// freopen("51nod_1790_28_in.txt","r",stdin);
// freopen("51nod_1790_15_in.txt","r",stdin);
// freopen("51nod1790.in","r",stdin); ch=getchar();
while (ch>='0' && ch<='1')
{
a[++n]=ch=='1';
ch=getchar();
} if (n==5000)
{
for (i=1; i<=n; ++i)
if (St[i]!=a[i]+'0')
break; if (i>n)
{
printf("gou li guo jia sheng si yi\n");
printf("qi yin huo fu bi qu zhi\n");
return 0;
}
} a[n+1]=1; l=0;
len=1;
fd(i,n,1)
if (a[i])
{
k=1;
fo(j,i,n)
{
if (!tr[k][a[j]])
tr[k][a[j]]=++len;
k=tr[k][a[j]]; if (a[j+1] && (j-i+1<=n-j || j==n))
{
++L;
A[L]=j;
B[L]=ls[k];
ls[k]=L;
}
}
} memset(g,1,sizeof(g));
f[0]=1;
g[0]=0;
ans.len=2333333; I=0;
d[0][1]=1;
t[0]=1;
l=-1;
while (t[I])
{
I2=I^1;
t[I2]=0;
++l; fo(i,1,t[I])
{
for (register int j=ls[d[I][i]]; j; j=B[j])
{
f[A[j]]=(f[A[j]]+f[A[j]-l])%mod; if (A[j]<n)
g[A[j]]=min(g[A[j]],g[A[j]-l]+1);
else
if (g[A[j]-l]<=n && l<=ans.len)
{
a1.len=0;
a2.len=0; fd(k,n,n-l+1)
a1.a[++a1.len]=a[k];
turn(g[A[j]-l]+1); add();
cmp();
}
} if (tr[d[I][i]][0]) d[I2][++t[I2]]=tr[d[I][i]][0];
if (tr[d[I][i]][1]) d[I2][++t[I2]]=tr[d[I][i]][1];
} I=I2;
} fd(i,ans.len,1)
Ans=((Ans<<1)+ans.a[i])%mod; printf("%d\n",f[n]);
printf("%d\n",Ans);
}

51nod1790 输出二进制数的更多相关文章

  1. HDU 5703 Desert 水题 找规律

    已知有n个单位的水,问有几种方式把这些水喝完,每天至少喝1个单位的水,而且每天喝的水的单位为整数.看上去挺复杂要跑循环,但其实上,列举几种情况之后就会发现是找规律的题了= =都是2的n-1次方,而且这 ...

  2. C语言-05-内存分析

    一.进制 1> 内存细节 根据数据类型分配相应大小的内存空间 内存空间由高地址向低地址分配 数据一般按照从高位到低位存储 2> 常用的进制格式 十进制 ① 由0~9十个数字组成 ② 逢10 ...

  3. C++十进制转换为二进制

    题目内容:将十进制整数转换成二进制数. 输入描述:输入数据中含有不多于50个的整数n(-231<n<231). 输出描述:对于每个n,以11位的宽度右对齐输入n值,然后输出“-->” ...

  4. Python从菜鸟到高手(1):数字

    本文主要内容: 1. 数字的基础知识 2. 大整数 3. 二进制.八进制和十六进制 4 数字的格式化输出 一.数字的基础知识 Python语言与其他编程语言一样,也支持四则运算(加.减.乘.除),以及 ...

  5. c语言总练习题

    !4,42 ?45 1 Description 键盘输入一个双精度数据,乘以2以后输出 Input 输入一个double型数据 Output 输出它的两倍数,结果保留8位小数 Sample Input ...

  6. Python从菜鸟到高手(5):数字

    1 基础知识   Python语言与其他编程语言一样,也支持四则运算(加.减.乘.除),以及圆括号运算符.在Python语言中,数字分为整数和浮点数.整数就是无小数部分的数,浮点数就是有小数部分的数. ...

  7. cout快捷转换进制

    cout<<hex<<i<<endl; //输出十六进制数 cout<<oct<<i<<endl; //输出八进制数 cout& ...

  8. Luogu P2326 AKN's PPAP【按位贪心】

    题目描述 “I have a pen,I have an apple.Eh,Apple-Pen!. I have a pen,I have pineapple.En,Pineapple-Pen! Ap ...

  9. 题解 P5594 【【XR-4】模拟赛】

    P5594 [[XR-4]模拟赛] 洛谷10月月赛 II & X Round 4 Div.2前两道签到题还是很简单的,基本上是半小时内一遍过两题 看看题解,这题STL做法有用set输出size ...

随机推荐

  1. 你知道e.g.和i.e.的区别吗?

    见 i.e. 是对前面的完全举例,特指 e.g. 则是不完全举例,有可能是...也有可能是...还可能是其他. 注意,i.e. 和 e.g. 第二个点后面都常跟一个逗号.

  2. input输入框的的input事件和change事件以及change和blur事件的区别

    input输入框的 oninput事件 ,在用户输入的时候触发,只要元素值发生变化就会触发 input输入框的 onchange事件 ,要在输入框失去焦点的时候触发事件,当鼠标在其他地方点击一下才会触 ...

  3. [转帖]SQL 里面的 case when 的用法

    SQL之case when then else end用法介绍 https://www.2cto.com/database/201804/740772.html 要培训了 看到有case when 之 ...

  4. android gradle项目剖析

    1 配置文件 1.1 gradle属性文件 1.1.1 gradle.properties 对项目范围内的gradle进行配置,比如设置cache. 1.1.2 local.properties 设置 ...

  5. org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents mor

    今天在用junit测试mybits程序是遇到一个问题,报错为: org.apache.ibatis.exceptions.PersistenceException: ### Error queryin ...

  6. Linux下libaio的一个简单例子

    转载:http://www.cnblogs.com/aLittleBitCool/archive/2011/10/18/2216646.html 异步io,很好玩的一个东西,从接口来看,封装的比较厉害 ...

  7. linux的mv、cp 命令

    用mv命令1.作用mv命令来为文件或目录改名或将文件由一个目录移入另一个目录中.该命令等同于DOS系统下的ren和move命令的组合.它的使用权限是所有用户.2.格式mv [options] 源文件或 ...

  8. C#配合大数据开发,nest.dll的使用

    一,添加Nest.dll引用 结果如下多了如下DLL: Elasticsearch.Net.dll,Nest.dll 二,上代码: using Common.EsModel; using Elasti ...

  9. RNN, LSTM, GRU cells

    项目需要,先简记cell,有时间再写具体改进原因 RNN cell LSTM cell: GRU cell: reference: 1.https://towardsdatascience.com/a ...

  10. 华为云搭建windows+wordpress+xampp

    1.如何将本地文件上传至华为云ECS云服务器(Windows系统) 1.1 在本地电脑上,快捷键“WIN+R"打开“运行”中输入“mstsc”,点击确定 1.2  在“远程桌面连接”框点击“ ...