【2017 ICPC 沈阳】G.Infinite Fraction Path 暴力优化
题意
给出 N 个城市编号为\(0,1,2...N-1\),每个城市都有一个价值 \(val_i\),范围为 \([0,9]\),第 \(i\) 个城市可以去 第 \((i^2+1)\%N\) 个城市。
如果从第 \(i\) 个城市出发,途径\(u_1,u_2,u_3...\) 等城市,那么会得到一个小数 \(0.val_i val_{u_1}val_{u_2}...\)
求出最大的一个小数的前 N 位。
思路
对于每一位肯定选择当前能找到的最大值。
我们就遍历 N 位。
初始,我们把价值最大的城市编号放入到一个vector:now中。
然后遍历 now 中的节点,找到下一位可能取值的最大值的所有编号,更新到 now 中,有个小优化:去除重复的位置。
就这样遍历 N 次即可。
比赛的时候觉得复杂度太高,没敢写。。。
代码
/*
* @Autor: valk
* @Date: 2020-08-21 11:06:28
* @LastEditTime: 2020-10-22 20:46:18
* @Description: 如果邪恶 是华丽残酷的乐章 它的终场 我会亲手写上 晨曦的光 风干最后一行忧伤 黑色的墨 染上安详
*/
#include <bits/stdc++.h>
#define fuck system("pause")
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mod = 1e9 + 7;
const int seed = 12289;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;
char str[N];
ll val[N], nxt[N], vis[N];
vector<ll> vec, ans, temp;
ll n;
void solve()
{
ll maxn = -1;
for (ll i = 1; i <= n; i++) {
maxn = max(maxn, val[i]);
}
for (ll i = 1; i <= n; i++) {
if (val[i] == maxn) {
vec.pb(i);
}
}
for (ll i = 1; i <= n; i++) {
ans.pb(val[vec[0]]);
maxn = -1;
for (ll j = 0; j < vec.size(); j++) {
maxn = max(maxn, val[nxt[vec[j]]]);
vis[vec[j]] = 0;
}
for (ll j = 0; j < vec.size(); j++) {
if (val[nxt[vec[j]]] == maxn && !vis[nxt[vec[j]]]) {
vis[nxt[vec[j]]] = 1;
temp.pb(nxt[vec[j]]);
}
}
vec = temp, temp.clear();
}
}
int main()
{
ll T, cas = 0;
scanf("%lld", &T);
while (T--) {
vec.clear(), ans.clear(), temp.clear();
memset(vis, 0, sizeof(vis));
scanf("%lld%s", &n, str + 1);
for (ll i = 1; i <= n; i++) {
val[i] = str[i] - '0';
nxt[i] = 1LL * ((i - 1) * (i - 1) + 1) % n + 1;
}
solve();
printf("Case #%lld: ", ++cas);
for (ll i = 0; i < ans.size(); i++) {
printf("%lld", ans[i]);
}
printf("\n");
}
return 0;
}