# 51Nod 算法马拉松17 最好的排列 贪心求解加高精度

486人阅读 评论(0)

### 题目大意

N10100$N \leq 10^{100}$

### 程序

//YxuanwKeith
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>

using namespace std;
typedef unsigned long long LL;

const int MAXN = 1e3 + 5;

struct Num {
int P[600];
};

char S[200];
map<LL,int> Map;
Num N, Get[1000], Len[1000], Work, One, Ans;
int Last[MAXN], Next[MAXN * 10], Go[MAXN * 10], tot;
int Cnt, Rd[MAXN], Ord[MAXN];

void Link(int u, int v) {
Next[++ tot] = Last[u], Last[u] = tot, Go[tot] = v;
}

LL GetHash(Num Now) {
LL Ans = 0;
for (int i = Now.P[0]; i; i --)
Ans = Ans * 11 + Now.P[i];
return Ans;
}

Num Dec(Num A) {
A.P[1] --;
int p = 1;
while (A.P[p] < 0) {
A.P[p] += 10;
A.P[p + 1] --;
p ++;
}
while (A.P[A.P[0]] == 0 && A.P[0] > 0) A.P[0] --;
return A;
}

Num Div2(Num A) {
for (int i = A.P[0]; i; i --) {
if (A.P[i] % 2 == 1 && i > 1) A.P[i - 1] += 10;
A.P[i] /= 2;
}
while (A.P[A.P[0]] == 0 && A.P[0] > 0) A.P[0] --;
return A;
}

Num Inc(Num A) {
A.P[1] ++;
int p = 1;
while (A.P[p] > 9) {
A.P[p] -= 10;
A.P[p + 1] ++;
p ++;
}
while (A.P[A.P[0] + 1] > 0) A.P[0] ++;
return A;
}

Num Add(Num A, Num B) {
Num C;
memset(C.P, 0, sizeof C.P);
C.P[0] = max(A.P[0], B.P[0]);
for (int i = 1; i <= C.P[0]; i ++) {
C.P[i] = C.P[i] + A.P[i] + B.P[i];
C.P[i + 1] += C.P[i] / 10;
C.P[i] = C.P[i] % 10;
}
while (C.P[C.P[0] + 1] > 0) C.P[0] ++;
return C;
}

Num Mul(Num A, Num B) {
Num C;
memset(C.P, 0, sizeof C.P);
C.P[0] = A.P[0] + B.P[0] - 1;
for (int i = 1; i <= A.P[0]; i ++)
for (int j = 1; j <= B.P[0]; j ++) {
C.P[i + j - 1] = C.P[i + j - 1] + A.P[i] * B.P[j];
C.P[i + j] = C.P[i + j] + C.P[i + j - 1] / 10;
C.P[i + j - 1] = C.P[i + j - 1] % 10;
}
while (C.P[C.P[0] + 1] > 0) C.P[0] ++;
return C;
}

bool Comp(Num A, Num B) {
if (A.P[0] < B.P[0]) return 1;
if (B.P[0] < A.P[0]) return 0;
for (int i = A.P[0]; i; i --) {
if (A.P[i] < B.P[i]) return 1;
if (B.P[i] < A.P[i]) return 0;
}
return 1;
}

int Div(Num Now) {
if (Now.P[0] == 0) return 0;
LL Hnum = GetHash(Now);
if (Map[Hnum]) return Map[Hnum];
Get[++ Cnt] = Now;
Map[Hnum] = Cnt;
Now = Dec(Now);
Num A = Div2(Now);
Num B;
if (Now.P[1] % 2 == 0) B = A; else
B = Inc(A);
int Ord = Cnt;
int NA = Div(A), NB = Div(B);
if (NA) Link(Ord, NA), Rd[NA] ++;
if (NB) Link(Ord, NB), Rd[NB] ++;
return Ord;
}

void Dfs(int Now) {
static int D[MAXN];
int top = 1;
D[top] = 1;
while (top) {
int Now = D[top --];
for (int p = Last[Now]; p; p = Next[p]) {
int v = Go[p];
Rd[v] --;
if (!Rd[v]) D[++ top] = v;
}
}
}

bool Cmp(int A, int B) {
return Comp(Get[A], Get[B]);
}

void Calc() {
for (int i = 1; i <= Cnt; i ++) Ord[i] = i;
sort(Ord + 1, Ord + 1 + Cnt, Cmp);
for (int i = 1; i <= Cnt; i ++) {
int Now = Ord[i];
Get[Now] = Inc(Get[Now]);
Num A = Div2(Get[Now]), B;
if (Get[Now].P[1] % 2 == 0) B = A; else
B = Inc(A);
Ans = Add(Ans, Mul(Mul(A, B), Sum));
}
for (int i = Ans.P[0]; i; i --)
printf("%d", Ans.P[i]);
}

int main() {
scanf("%s", S + 1);
N.P[0] = strlen(S + 1);
for (int i = N.P[0]; i; i --) N.P[i] = S[N.P[0] - i + 1] - '0';
One.P[0] = One.P[1] = 1;

Len[1] = One;
Div(N);
Dfs(0);
Calc();
}
1
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：101597次
• 积分：2711
• 等级：
• 排名：第14076名
• 原创：143篇
• 转载：4篇
• 译文：0篇
• 评论：136条
评论排行
最新评论