博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Codeforces866E_CF866E】Hex Dyslexia(Structure & DP)
阅读量:4563 次
发布时间:2019-06-08

本文共 5710 字,大约阅读时间需要 19 分钟。

It's my first time to write a blog in EnglishChinglish, so it may be full of mistakes in grammar.

Problem:

Analysis:

First, we determine \(S\geq T\), then \(S-T=A\), where \(A\) is the known number, and \(S\) is shuffled from \(T\). Then move \(T\) to the right so we have \(S=T+A\).

Think about how to calculate \(T+A\) in writing. If undo all Jinwei (This is Chinese Pinyin. I don't know how to express it in English. Jinwei means if \(T_i+A_i\) is not less than \(16\) in hex, then subtract \(16\) from it and add \(1\) to \(S_{i+1}\)), then for every digit, it's \(T_i+A_i=S'_i\) (\(S'_i\) can be greater than \(15\) now). Now, \(\sum T_i + \sum A_i = \sum S'_i\). But because of \(S\) is shuffled from \(T\), \(\sum T_i\) should be equal to \(\sum S_i\). Fortunately, every Jinwei can subtract \(15\) from \(\sum S'_i\), because Jinwei is subtracting \(16\) from \(S'_i\) and add \(1\) to \(S'_{i+1}\). Thus, possible \(S\) and \(T\) exist only when \(A\) is divisible by \(15\).

If \(A\) is divisible by \(15\), \(\frac{\sum A_i}{15}\) is the times that Jinwei happens. We can determine whether a Jinwei happens on a dight one after another. Jinwei can't happen on the hightest dight, so the total number of ways that exactly \(\frac{\sum A_i}{15}\) Jinweis happen is \(C_{|T|-1}^{\frac{\sum A_i}{15}}\), where \(|T|\) is the length of \(T\). It's not greater than \(C_{13}^{\lfloor \frac{13}{2} \rfloor}=1716\).

Now we have determined which digits Jinweis happen on, so we can offset the effect of Jinweis by changing \(A\). Specifically, if a Jinwei happens on the digit \(i\), so that \(T_i+A_i-16=S_i\) and \(T_{i+1}+A_{i+1}+1=S_{i+1}\), we can subtract \(16\) from \(A_i\) and add \(1\) to \(A_{i+1}\) ( \(A_i\) now can be more than \(15\) or less than \(0\) ) , then for every \(i\), there's \(T_i+A_i=S_i\). In this way, every digit will be independent. (From now on, \(A\) is the changed one. )

Let's try to structure a possible answer. It should be noticed that now there's no Jinwei happens, or the answer is invalid. An useful fact is, there's at least one \(T_i\) that is \(0\), or subtract the minimum in \(T\) from each \(T_i\) and \(S_i\), so that every \(T_i+A_i=S_i\) is valid as well, but we get a less \(T\). To minimize \(T\), let's put \(0\) on the highest digit directly.

Define \(f[S]\) is the minimum of \(T\) when the digits in the set \(S\) have been decided. Because the number on the highest digit must be \(0\) and there's no need to consider that digit, \(S\) is not contain the highest digit. Each time we decide put \(a\) on a digit \(i\), we'll get a new number \(a+A_i\) that waiting to be put. This new number after deciding all digits in the set \(S\) is exactly \(\sum_{i\in S}A_i+A_{|T|-1}\) ( \(|T|-1\) is the highest digit) , because the first number we put is \(0\), and then we get \(A_{|T|-1}\); the second number we put is \(A_{|T|-1|}\) on digit \(i\) and we get \(A_{|T|-1}+A_i\) and so on. In the end, because of our way to change \(A_i\), \(\sum A_i\) must be \(0\), and \(0\) has already been put on the highest digit. How lucky we are!

Now the problem is easy. For every \(S\), choose a digit \(i\) and try to put the new number \(sum[S]\) (in the code it's called like that, but I don't know why, maybe because Tzz is a mouther) on it.

For more details, please read the code.

Code:

#include 
#include
#include
#include
#include
using namespace std;namespace zyt{ template
inline bool read(T &x) { char c; bool f = false; x = 0; do c = getchar(); while (c != EOF && c != '-' && !isdigit(c)); if (c == EOF) return false; if (c == '-') f = true, c = getchar(); do x = x * 10 + c - '0', c = getchar(); while (isdigit(c)); if (f) x = -x; return true; } inline bool read(char &c) { do c = getchar(); while (c != EOF && !isgraph(c)); return c != EOF; } template
inline void write(T x) { static char buf[20]; char *pos = buf; if (x < 0) putchar('-'), x = -x; do *pos++ = x % 10 + '0'; while (x /= 10); while (pos > buf) putchar(*--pos); } inline void write(const char *const s) { printf("%s", s); } typedef long long ll; const int N = 15, D = 16, INF = 0x3f3f3f3f; const ll LINF = 0x3f3f3f3f3f3f3f3fLL; int len, arr[N], sum[1 << N]; ll ans = LINF, dp[1 << N]; inline bool check(const int a, const int p) { return a & (1 << p); } void solve() { memset(sum, 0, sizeof(int[1 << len])); memset(dp, INF, sizeof(ll[1 << len])); for (int i = 0; i < (1 << (len - 1)); i++) { sum[i] = arr[len - 1]; for (int j = 0; j < len - 1; j++) if (check(i, j)) sum[i] += arr[j]; } dp[0] = 0; for (int i = 0; i < (1 << (len - 1)); i++) { if (sum[i] < 0 || sum[i] >= D || dp[i] > ans || dp[i] == LINF) continue; for (int j = 0; j < len - 1; j++) if (!check(i, j)) dp[i | (1 << j)] = min(dp[i | (1 << j)], dp[i] + ((ll)sum[i] << (j << 2))); } ans = min(ans, dp[(1 << (len - 1)) - 1]); ; } void dfs(const int pos, const int rest) { if (pos < 0) { if (!rest) solve(); return; } dfs(pos - 1, rest); if (pos && rest) { ++arr[pos], arr[pos - 1] -= D; dfs(pos - 1, rest - 1); --arr[pos], arr[pos - 1] += D; } } int work() { char c; while (read(c)) { if (isdigit(c)) arr[len++] = c - '0'; else arr[len++] = c - 'a' + 10; } reverse(arr, arr + len); int sum = 0; for (int i = 0; i < len; i++) sum += arr[i]; if (sum % (D - 1)) { write("NO"); return 0; } dfs(len - 1, sum / (D - 1)); if (ans == LINF) write("NO"); else { static char buf[20]; char *pos = buf; while (len--) *pos++ = ((ans % D < 10) ? ans % D + '0' : ans % D - 10 + 'a'), ans /= D; while (pos > buf) putchar(*--pos); } return 0; }}int main(){ return zyt::work();}

转载于:https://www.cnblogs.com/zyt1253679098/p/10418614.html

你可能感兴趣的文章
没写完,没调完,咕咕咕的代码
查看>>
Android Studio使用技巧:导出jar包
查看>>
Problem E. TeaTree - HDU - 6430 (树的启发式合并)
查看>>
Kafka序列化和反序列化与示例
查看>>
win10下VS2010中文输入法切换为英文卡死
查看>>
retinex相关代码汇总
查看>>
Cortex-M3 异常返回值EXC_RETURN
查看>>
kettle 转换字段遇到问题(couldn't get row from result set)——摘
查看>>
nginx首页根据IP跳转
查看>>
【2019-08-20】有点目标,有点计划,有点目的
查看>>
【2019-09-10】美,真的跟年龄无关
查看>>
【2019-09-28】少,但更好
查看>>
【2019-09-13】耐心观察是一种技能
查看>>
mysql数据库2-常用命令
查看>>
安卓开发环境搭建(转)
查看>>
Harris角点检测
查看>>
Struts2的处理流程及为Action的属性注入值
查看>>
设计中最常用的CSS选择器
查看>>
Maven项目打包成可执行Jar文件
查看>>
nginx http proxy 正向代理
查看>>