标签:stdin 最大 c++ targe std min lan out 原理
网址:https://codeforces.com/gym/100851
考虑如下线性同余发生器:$x=(a*x+b)mod$ $c$,给出$1e4$个线性同余发生器,在这些线性同余发生器生成的数的序列中每一个序列都任意挑一个数,使得它们的和最大并且不被$k$整除,输出和的值和各个位置,如果不存在输出$-1$。$c\leq1e3$。
线性同余发生器的值一定在不超过$c$个数就重复循环。所以只需要取其生成的前$c$个数的第k大。如果它们的和不被$k$整除,直接输出即可,如果被$k$整除,找到某个序列的第二大,使其和第一大的差值最小,且差值不被$k$整除,换上这个第二大即可。
(很奇怪,我不知道为什么我排序了还不能直接按顺序取第二大而是需要更新,不然会$WA$)。
AC代码:
#include <bits/stdc++.h> using namespace std; const int N = 1e4 + 5; typedef long long ll; vector<pair<int, int> >v; pair<int, int>p[N], dif[N]; bool vis[1005]; int main() { #ifndef _Aya //freopen("generators.in", "r", stdin); //freopen("generators.out", "w", stdout); #endif int n, k, a, b, c, x; scanf("%d%d", &n, &k); for (int i = 1; i <= n; ++i) { memset(vis, 0, sizeof(vis)); v.clear(); scanf("%d%d%d%d", &x, &a, &b, &c); v.push_back(make_pair(x, 0)); vis[x] = 1; for (int j = 1; j < c; ++j) { x = (a * x + b) % c; if (!vis[x]) v.push_back(make_pair(x, j)), vis[x] = 1; else break; } dif[i] = make_pair(-1, -1); sort(v.begin(), v.end(), greater<pair<int, int> >()); p[i] = v[0]; for (int j = 1; j < v.size(); ++j) if ((v[0].first - v[j].first) % k != 0 && v[j].first > dif[i].first) dif[i] = v[j]; assert(p[i].first > dif[i].first); } ll sum = 0; for (int i = 1; i <= n; ++i) sum += p[i].first; if (sum % k) { printf("%lld\n", sum); for (int i = 1; i <= n; ++i) printf("%d%c", p[i].second, " \n"[i == n]); } else { int minn = 1e4, minpos = 0; for (int i = 1; i <= n; ++i) if (dif[i].second != -1 && p[i].first - dif[i].first < minn) minn = p[i].first - dif[i].first, minpos = i; if (!minpos) printf("-1\n"); else { p[minpos] = dif[minpos]; sum -= minn; printf("%lld\n", sum); for (int i = 1; i <= n; ++i) printf("%d%c", p[i].second, " \n"[i == n]); } } return 0; }
Gym100851G Generators 思维 (鸽笼原理)
标签:stdin 最大 c++ targe std min lan out 原理
原文地址:https://www.cnblogs.com/Aya-Uchida/p/12589389.html