显然需要贪心,重叠越长越好,这样最终的串长尽可能短。
需要注意的是,不要考虑中间结果,显然是个状态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. 【转】Qt使用自带的windeployqt 生成exe来发布软件

    集成开发环境 QtCreator 目前生成图形界面程序 exe 大致可以分为两类:Qt Widgets Application  和 Qt Quick Application.下面分别介绍这两类exe ...

  2. ios 数字禁止变成电话号码

    1.使用meta来限制页面不转换电话号码   <meta name="format-detection"content="telphone=no"/> ...

  3. android 获取手机号

    android 获取手机号码,由于运营商的管理方式的不同,所以获取手机号码的方式也可能完全相同.现在很多运营商并不会把手机号码存入sim卡中. 最简单的,比如说中国移动并不将手机号保存在sim卡中,只 ...

  4. php字符串首字母转换大小写的实例分享

    php中对字符串首字母进行大小写转换的例子. in: 后端程序首字母变大写:ucwords() <?php $foo = 'hello world!'; $foo = ucwords($foo) ...

  5. Demo学习: FileUpload

    FileUpload 文件上传,学习TUniFileUpload控件的使用 TUniFileUpload主要属性: Filter: 文件类型过滤,这个属性在web模式下是无效的,UniGUI目前版本还 ...

  6. select 函数实现 三种拓扑结构 n个客户端的异步通信 (完全图+线性链表+无环图)

    一.这里只介绍简单的三个客户端异步通信(完全图拓扑结构) //建立管道 mkfifo open顺序: cl1 读 , cl2 cl3 向 cl1写 cl2 读 , cl1 cl3 向 cl2写 cl3 ...

  7. shell调用sqlplus批量执行sql文件

    在最近的工作中,经常需要批量执行一些DML, DDL, PL/SQL语句或导入一些Function, Procedure.因为support的国家比较多,常常需要一个登陆到一个国家的数据库上执行完成后 ...

  8. EXTJS 资料 combo 点一次触发一次

    { xtype: 'combo', id: 'ApplyToModel', name: 'ApplyToModel', store: comStoreApplyToModel, valueField: ...

  9. 【BZOJ3262】 陌上花开

    Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...

  10. 微软职位内部推荐-Pricipal Dev Manager for Application Ecosystem & Service

    微软近期Open的职位: Location: China, BeijingDivision: Operations System Group Engineering Group OverviewOSG ...