显然需要贪心,重叠越长越好,这样最终的串长尽可能短。
需要注意的是,不要考虑中间结果,显然是个状态dp。
先做预处理去重,然后求任意一对串的公共长度。

 /* 3828 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 const int INF = 0x3f3f3f3f;
const int maxl = ;
const int maxn = ;
const int mod = ;
__int64 a[maxn];
char word[maxn][maxl];
string sw[maxn];
int nxt[maxl];
int Len[maxn];
bool visit[maxn];
int dp[<<][];
int M[][];
int n; void f(char *s, __int64 x) {
int l = ;
while (x) {
s[l] = (x & ) + '';
++l;
x >>= ;
}
s[l] = '\0';
reverse(s, s+l);
} void getnext(char *s) {
int i = , j = -;
int l = strlen(s); nxt[] = -;
while (i < l) {
if (j==- || s[i]==s[j]) {
++i;
++j;
nxt[i] = j;
} else {
j = nxt[j];
}
}
} bool match(char *d, char *s, int ld, int ls) {
int i = , j = ; while (i < ld) {
if (d[i] == s[j]) {
++i;
++j;
} else {
j = nxt[j];
if (j == -) {
j = ;
++i;
}
}
if (j == ls)
return true;
} return false;
} void cover() {
memset(visit, false, sizeof(visit));
rep(i, , n) {
getnext(word[i]);
rep(j, , n) {
if (i == j)
continue;
if (match(word[j], word[i], Len[j], Len[i])) {
visit[i] = true;
break;
}
}
} int nn = ;
rep(i, , n) {
if (!visit[i]) {
strcpy(word[nn], word[i]);
Len[nn] = strlen(word[nn]);
++nn;
}
}
n = nn;
} bool judge(int l, char *sa, char *sb) {
rep(i, , l) {
if (sa[i] != sb[i])
return false;
}
return true;
} int LongFix(int a, int b) {
per(l, , Len[a]) {
if (Len[b]>=l && judge(l, word[a]+Len[a]-l, word[b]))
return l;
} return ;
} void calc() {
rep(i, , n) {
rep(j, , n) {
if (i == j) {
M[i][j] = Len[i];
continue;
}
M[i][j] = LongFix(i, j);
}
}
} void solve() {
sort(a, a+n);
n = unique(a, a+n) - a;
rep(i, , n) {
f(word[i], a[i]);
Len[i] = strlen(word[i]);
}
cover();
calc(); int mst = << n; memset(dp, INF, sizeof(dp));
rep(i, , n)
dp[<<i][i] = Len[i]; rep(i, , mst) {
rep(j, , n) {
if (dp[i][j]==INF || (i&(<<j))==)
continue; rep(k, , n) {
if (i & (<<k))
continue; int nst = i | (<<k);
dp[nst][k] = min(dp[nst][k], dp[i][j]+Len[k]-M[k][j]);
}
}
} rep(i, , n)
sw[i] = string(word[i]); int st = mst - ;
int p = -; string str = "";
while () {
int mn = INF, v;
string tstr, mnstr; rep(i, , n) {
if ((st & (<<i)) == )
continue; int tmp = dp[st][i];
if (p >= ) {
tmp -= M[p][i];
tstr = sw[i].substr(M[p][i]);
} else {
tstr = sw[i];
} if (tmp<mn || (tmp==mn && tstr<mnstr)) {
mn = tmp;
mnstr = tstr;
v = i;
}
} str += mnstr;
p = v;
st ^= ( << v);
if (st == )
break;
} int length = str.length(), base = ;
__int64 ans = ; per(i, , length) {
if (str[i] == '')
ans = (ans + base) % mod;
base = (base + base) % mod;
} printf("%I64d\n", ans);
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif while (cin >> n) {
rep(i, , n)
cin >> a[i];
solve();
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}

【HDOJ】3828 A + B problem的更多相关文章

  1. 【HDOJ】4729 An Easy Problem for Elfness

    其实是求树上的路径间的数据第K大的题目.果断主席树 + LCA.初始流量是这条路径上的最小值.若a<=b,显然直接为s->t建立pipe可以使流量最优:否则,对[0, 10**4]二分得到 ...

  2. 【HDOJ】4267 A Simple Problem with Integers

    树状数组.Easy. /* 4267 */ #include <iostream> #include <string> #include <map> #includ ...

  3. 【HDOJ】1016 Prime Ring Problem

    经典DP,写的可能麻烦了一些. #include <stdio.h> #define false 0 #define true 1 ]; ]; ]; void DFS(int, int, ...

  4. 【HDOJ】P2058 The sum problem

    题意很简单就是给你一个N和M,让你求在1-N的那些个子序列的值等于M 首先暴力法不解释,简单超时 再仔细想一想可以想到因为1-N是一个等差数列,可以运用我们曾经学过的只是来解决 假设开始的位置为s,结 ...

  5. 【BZOJ3489】A simple rmq problem(KD-Tree)

    [BZOJ3489]A simple rmq problem(KD-Tree) 题面 BZOJ 题解 直接做肯定不好做,首先我们知道我们是一个二维平面数点,但是限制区间只能出现一次很不好办,那么我们给 ...

  6. 【CF903G】Yet Another Maxflow Problem 线段树

    [CF903G]Yet Another Maxflow Problem 题意:一张图分为两部分,左边有n个点A,右边有m个点B,所有Ai->Ai+1有边,所有Bi->Bi+1有边,某些Ai ...

  7. 【BZOJ3489】A simple rmq problem

    [BZOJ3489]A simple rmq problem 题面 bzoj 题解 这个题不强制在线的话随便做啊... 考虑强制在线时怎么搞 预处理出一个位置上一个出现的相同数的位置\(pre\)与下 ...

  8. 【BZOJ3489】A simple rmq problem kd-tree

    [BZOJ3489]A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过 ...

  9. 【题解】CF986E Prince's Problem(树上差分+数论性质)

    [题解]CF986E Prince's Problem(树上差分+数论性质) 题目大意: 给定你一棵树,有点权\(val_i\le 10^7\).现在有\(m\)组询问给定参数\(x,y,w\)问你对 ...

随机推荐

  1. Eclipse必须掌握的快捷键

    Eclipse快捷键 Ctrl +  / 添加//注释.删除//注释 Ctrl + 1 快速修复错误 Ctrl + Shift + f 格式化文档 Shift + Enter Shift + Ctrl ...

  2. DTCMS自定义标签,获取所有栏目文章列表TOP,以及文章通用URL

    网站最近更新等地方,发现DTCMS没有获取所有栏目文章列表的标签,只能自己写 思路:获取所有栏目文章列表不难,难点在于linkurl的写法 1.制作获取所有文章列表标签 DTcms.Web.UI\La ...

  3. Unity学习笔记(3):获取对象

    在上一篇文章中(Unity映射注册)中概要介绍了Unity中的映射机制,本节主要介绍对象获取,包括默认获取,通过名称获取,获取全部对象,同时通过加载配置文件,然后再获取对象. 通过代码获取对象 方式1 ...

  4. 正则表达式模块re

    正则表达式通过特定的式子匹配某种类型的字符串.对字符串进行匹配验证或者从大量的字符串里提取出特定的信息. 正则表达式包含普通字符和特殊字符.大部分的普通字符如‘A’或‘0’可以简单的来匹配自己.如te ...

  5. Hello World for U (20)

    Given any string of N (>=5) characters, you are asked to form the characters into the shape of U. ...

  6. ORA-19809: 超出了恢复文件数的限制

    实验环境:Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod 实验背景:向tough.t中插入40万条记录,然后rollb ...

  7. 关于MySQL Connector/C++那点事儿

    如果从官方直接下载的库使用时遇到类似如下的问题: 原因是官方提供的库文件版本与需要的库版本不匹配,提供的debug版本使用的是MT版本,在debug模式下会出现内存错误,导致crash. TestC. ...

  8. EXTJS 4.2 资料 控件textfield中fieldLabel去掉冒号,控件label的长度

    代码: labelSeparator: '', // 去掉laebl中的冒号 labelWidth: 10,//控件label的长度

  9. python学习笔记24(路径与文件 (os.path包, glob包))

    os.path模块主要用于文件的属性获取,在编程中经常用到,以下是该模块的几种常用方法. >>> import os.path >>> path = '/home/ ...

  10. Java第一阶段总结

    学习java已经一个多月的时间了,第一阶段总算完成了. 这中间遇到很多问题,通过问同学问学长,收获了很多,但也知道自己和其他同学相差很远.他们java第一阶段只用了不到一个月的时间,而我拖了很长时间, ...