显然需要贪心,重叠越长越好,这样最终的串长尽可能短。
需要注意的是,不要考虑中间结果,显然是个状态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. Projected Coordinate Systems

    Coordinate Systems Projected Coordinate Systems This is an archive of a previous version of the ArcG ...

  2. 【CLR VIA C#】读书笔记

    工作几年了才看,记录下笔记备忘. 章节 笔记 1.CLR的执行模型 公共语言运行时(Common Language Runtime,CLR) 源代码-->编译器检查语法和分析源代码-->托 ...

  3. Ajax的理解

    初学JS,一直认为Ajax是个很高级的.不可亵玩的东西.这两天怀着忐忑的心情接触了一下它, 感觉它并没有想象中的那么难理解. 其实,Ajax就是浏览器端向服务器请求资源的一个对象(方法). 就跟打电话 ...

  4. String Subtraction

    Given two strings S1 and S2, S = S1 - S2 is defined to be the remaining string after taking all the ...

  5. 种子填充找连通块 floodfill

    Description Due to recent rains, water has pooled in various places in Farmer John's field, which is ...

  6. javascript看你能够做对几题

    http://ourjs.com/detail/52fb82e13bd19c4814000001

  7. Perl内置变量速查表

    [ 文件句柄 ] $| 如果非零, 则在对当前选定的文件执行写或打印操作后强制清除缓冲区 $% 当前选中文件句柄的当前页码 $= 当前选中文件句柄的当前页面长度 $- 当前选中文件句柄的页面剩余长度 ...

  8. easy ui 表单提交添加遮罩,避免数据重复提交

    如下图: //点击提交按钮保存数据 $('#btn_submit').click(function () { //增加遮罩层 $.messager.progress({ title: '温馨提示', ...

  9. MyBatis对不同数据库的主键生成策略

    本文转自:http://289972458.iteye.com/blog/1001851  http://hi.baidu.com/zim_it/blog/item/8a2bd11205f5b56ec ...

  10. WDS无线桥接

    因为放假回家,长时间不在家,家里也没什么人,所以也就没有网可以用.为了两个月办宽带又不值得,太过浪费了.于是就只能蹭网用了.当然,要和邻居打个招呼或者你能搞定密码的情况下不打招呼(嘿嘿...).但是有 ...