CodeForces Contest #1114: Round #538 (Div. 2)

比赛传送门:CF #1114

比赛记录:点我

又 FST 了。


【A】Got Any Grapes?

题意简述:

有三个人,第一个人需要吃绿色葡萄至少 \(a\) 个,第二个人需要吃绿色和紫色葡萄至少 \(b\) 个,第三个人需要吃绿色、紫色和黑色葡萄至少 \(c\) 个。

有 \(x\) 个绿色葡萄,\(y\) 个紫色葡萄,\(z\) 个黑色葡萄,问是否能够满足三个人的要求。

题解:

#include <cstdio>

int main() {
    int x, y, z, a, b, c;
    scanf("%d%d%d%d%d%d", &x, &y, &z, &a, &b, &c);
    if (a < x || a + b < x + y || a + b + c < x + y + z) puts("NO");
    else puts("YES");
    return 0;
}

【B】Yet Another Array Partitioning Task

题意简述:

一个长度为 \(n\) 的数组 \(a_i\),要把它分成 \(k\) 个连续段(每段长度大于等于 \(m\)),每段的贡献是其中最大的 \(m\) 个元素,求一种分割方案使得总贡献最大。

题解:

把最大的 \(m\cdot k\) 个数提取出来,暴力分割。

#include <cstdio>
#include <algorithm>

typedef long long LL;

int N, M, K;
int A[200005], B[200005];
LL Ans = 0;

int main(){
    scanf("%d%d%d", &N, &M, &K);
    for (int i = 1; i <= N; ++i) {
        scanf("%d", &A[i]);
        B[i] = i;
    }
    std::sort(B + 1, B + N + 1, [](int i, int j) { return A[i] > A[j]; });
    std::sort(B + 1, B + M * K + 1);
    for (int i = 1; i <= M * K; ++i) Ans += A[B[i]];
    printf("%lld\n", Ans);
    for (int i = M; i < M * K; i += M) printf("%d ", B[i]);
    puts("");
    return 0;
}

【C】Trailing Loves (or L‘oeufs?)

题意简述:

求 \(n!\)(\(n\) 的阶乘)在 \(b\) 进制下末尾有几个 \(0\)。(\(1\le n\le 10^{18}\),\(2\le b\le 10^{12}\))

题解:

相当于求最大的 \(k\) 使得 \(b^k|n!\)。记这个值为 \(v_b(n)\)。

对于 \(b=p\) 是质数的情况,数论告诉我们有:\(v_p(n)=\sum_{i=1}^{\infty}\lfloor\frac{n}{p^i}\rfloor=\lfloor\frac{n}{p}\rfloor+\lfloor\frac{n}{p^2}\rfloor+\lfloor\frac{n}{p^3}\rfloor+\cdots\)。

\(v_p(n)\) 给出了 \(n!\) 的标准分解式中 \(p^k\) 因子的次方数 \(k\)。

这启发我们将 \(b\) 质因数分解:\(b=p_1^{e_1}p_2^{e_2}\cdots p_k^{e_k}\)。

则有:

\[v_b(n)=\min_{i=1}^{k}\left(\left\lfloor\frac{v_{p_i}(n)}{e_i}\right\rfloor\right)\]

对于 \(v_p(n)\) 可以用这个方法计算:\(v_p(n)=\begin{cases}0&,n=0\\\lfloor\frac{n}{p}\rfloor+v_p(\lfloor\frac{n}{p}\rfloor)&,n>0\end{cases}\)。

#include <cstdio>
#include <algorithm>

typedef long long LL;
const LL INF = 0x3f3f3f3f3f3f3f3f;

LL N, b;
LL p[25]; int e[25], cnt;
LL Ans = INF;

int main() {
    scanf("%lld%lld", &N, &b);
    for (LL i = 2; i * i <= b; ++i) if (b % i == 0) {
        p[++cnt] = i, e[cnt] = 0;
        while (b % i == 0) b /= i, ++e[cnt];
    } if (b > 1) p[++cnt] = b, e[cnt] = 1;
    for (int i = 1; i <= cnt; ++i) {
        LL num = 0, m = N;
        while (m) num += m / p[i], m /= p[i];
        Ans = std::min(Ans, num / e[i]);
    }
    printf("%lld\n", Ans);
    return 0;
}

【D】Flood Fill

题意简述:

一个长度为 \(n\) 的序列 \(c_1,c_2,\ldots,c_n\)。

你可以选择一个位置 \(pos\),每次操作你把 \(pos\) 所在联通块全部变成一个数。

问最少花费几次操作可以把整个序列变成同一个数。

一个联通块指 \(c_i\) 全部相同的连续一段。

题解:

先把序列 unique 一下,得到联通块个数。

令 \(\mathrm{f}[i][j]\) 为把序列的第 \(i\) 位到第 \(j\) 位全部变成同一种颜色要花费的最小操作数。

转移:\(\mathrm{f}[i][j]=1+\begin{cases}\min(\mathrm{f}[i+1][j],\mathrm{f}[i][j-1])&,c[i]\ne c[j]\\\mathrm{f}[i+1][j-1]&,c[i]=c[j]\end{cases}\)。

#include <cstdio>
#include <algorithm>

const int MN = 5005;

int N, c[MN];
int f[MN][MN];

int main() {
    scanf("%d", &N);
    for (int i = 1; i <= N; ++i)
        scanf("%d", &c[i]);
    N = std::unique(c + 1, c + N + 1) - c - 1;
    for (int i = 1; i <= N; ++i)
        f[i][i] = 0;
    for (int Q = 2; Q <= N; ++Q) {
        for (int i = 1; i <= N - Q + 1; ++i) {
            int j = i + Q - 1;
            if (c[i] == c[j]) f[i][j] = f[i + 1][j - 1] + 1;
            else f[i][j] = std::min(f[i + 1][j], f[i][j - 1]) + 1;
        }
    }
    printf("%d\n", f[1][N]);
    return 0;
}

【E】Arithmetic Progression

题意简述:

这是一道交互题。

交互器有一个长度为 \(n\)(\(2\le n\le 10^6\))的等差数列 \(a_1,a_2,\ldots,a_n\)。保证 \(0\le a_i\le 10^9\),且公差 \(d=a_2-a_1>0\)。

但是这个等差数列被随机打乱了,给定 \(n\),你需要做出不超过 \(60\) 次询问,得到 \(a_1\) 和公差 \(d\)。

你有两种询问:

  1. ? i(\(1\le i\le n\)):询问 \(a_i\) 的值,注意这里返回的是打乱后的。
  2. > x(\(0\le x\le 10^9\)):询问这个等差数列中是否存在一个数 \(a_i\) 满足 \(a_i>x\)。

题解:

首先使用不超过 \(30\) 次询问 > x,二分查找找到最大的数 \(max\)。

令 \(d=0\)。

然后使用若干次 ? i,这里 \(i\) 是在 \(1\) 到 \(n\) 内等概率随机的,每次得到一个数 \(a_i\),令 \(d=\gcd(d,max-a_i)\)。

最后 \(a_1=max-(n-1)d\)。

为什么这样是正确的?显然找到最大的数的询问次数的确不超过 \(30\) 次。

接下来还有至少 \(60-30=30\) 次操作,用于更新公差 \(d\)。

答案正确的可能性等价于在 \(0\) 到 \(n-1\) 中等概率随机选取至少 \(30\) 个数,并且它们的 \(\gcd\) 等于 \(1\)。

可以证明答案错误的概率小于 \(1.86\times 10^{-9}\)。

注意选取合适的随机数生成器,无良出题人专门卡了普通的 rand()

#include <cstdio>
#include <algorithm>

inline unsigned Uran() {
    static unsigned x = 20021005;
    return x ^= x << 17, x ^= x >> 13, x ^= x << 5;
}
inline int Mran(int L, int R) {
    return Uran() % (R - L + 1) + L;
}

int N, cnt, d;

int main() {
    scanf("%d", &N);
    int l = N, r = 1e9, mid, x, mx = N - 1;
    while (l <= r) {
        mid = (l + r) >> 1;
        printf("> %d\n", mid - 1);
        fflush(stdout);
        scanf("%d", &x);
        ++cnt;
        if (x) mx = mid, l = mid + 1;
        else r = mid - 1;
    }
    while (cnt < 60) {
        printf("? %d\n", Mran(1, N));
        fflush(stdout);
        scanf("%d", &x);
        ++cnt;
        d = std::__gcd(d, mx - x);
    }
    printf("! %d %d\n", mx - (N - 1) * d, d);
    return 0;
}

【F】Please, another Queries on Array?

题意简述:

一个长度为 \(n\) 的序列 \(a_1,a_2,\ldots,a_n\)。有 \(q\) 次操作,每次操作为以下两种之一:

  1. MULTIPLY l r x:将 \(a_l\) 到 \(a_r\) 之间(包括 \(a_l\) 和 \(a_r\))的所有数乘以 \(x\)。
  2. TOTIENT l r:询问 \(\varphi(\prod_{i=l}^{r}a_i)\pmod{10^9+7}\),其中 \(\varphi(x)\) 表示 \(x\) 的欧拉函数值。

数据范围:\(1\le l\le r\le n\le 4\cdot 10^5\),\(1\le q\le 2\cdot 10^5\),\(1\le a_i,x\le 300\)。

题解:

首先想到使用线段树维护区间。

注意到 \(a_i\) 和 \(x\) 很小,不超过 \(300\)。

又有 \(\varphi(x)=x\prod_{p|x}\frac{p-1}{p}\),这提示我们维护区间乘积以及区间质因数集合。

发现 \(300\) 以内的质数个数只有 \(62\) 个,正好在 long long 的位数范围内,这提示我们状压集合存入 long long 中。

变成了基础线段树例题,复杂度 \(\mathrm{O}((n+q)\log^2 n)\)。使用原根化乘为加可以做到 \(\mathrm{O}((n+q)\log n)\)。

这里给出使用原根和 BSGS 打表的代码,\(10^9+7\) 的原根是 \(5\)。

#include <cstdio>
#include <algorithm>
#include <map>

typedef unsigned long long LL;
typedef std::pair<LL, LL> pll;
const LL Mod = 1000000007, eM = 1000000006, G = 5;
const int MX = 301;

inline LL qPow(LL b, int e) {
    LL a = 1;
    for (; e; e >>= 1, b = b * b % Mod)
        if (e & 1) a = a * b % Mod;
    return a;
}

const int E[MX] = {0, 0, 381838282, 884237698, 763676564, 1, 266075974, 936544532, 145514840, 768475390, 381838283, 649233168, 647914256, 144547565, 318382808, 884237699, 527353122, 895459693, 150313666, 701153241, 763676565, 820782224, 31071444, 82047235, 29752532, 2, 526385847, 652713082, 700221090, 347375814, 266075975, 198670980, 909191404, 533470860, 277297969, 936544533, 532151948, 289190395, 82991517, 28785257, 145514841, 802264261, 202620500, 24616936, 412909726, 768475391, 463885517, 730741137, 411590814, 873089058, 381838284, 779697385, 908224129, 616590335, 34551358, 649233169, 82059366, 585390933, 729214096, 178404868, 647914257, 234516540, 580509262, 705019916, 291029680, 144547566, 915309142, 351358075, 659136251, 966284933, 318382809, 557546595, 913990230, 559624399, 671028677, 884237700, 464829799, 585777694, 410623539, 414776906, 527353123, 536950774, 184102537, 809672376, 584458782, 895459694, 406455218, 231613506, 794748008, 689565125, 150313667, 81092091, 845723799, 82908672, 112579413, 701153242, 793429096, 993378125, 254927334, 417708552, 763676566, 495914368, 161535661, 991051336, 290062405, 820782225, 998428617, 326036185, 416389640, 525353314, 31071445, 173428087, 463897648, 429750477, 967229215, 82047236, 111052372, 913022955, 560243150, 832004219, 29752533, 298466330, 616354822, 686501953, 962347544, 3, 86858192, 155622902, 672867962, 908854634, 526385848, 26958408, 297147418, 637697767, 733196357, 652713083, 40974527, 540374100, 348123209, 293399235, 700221091, 614978829, 939384877, 793780733, 295828506, 347375815, 941462681, 757326750, 52866953, 109607515, 266075976, 468364065, 846668081, 663935077, 967615976, 198670981, 792461821, 967234449, 796615188, 500828027, 909191405, 18591761, 918789056, 238291131, 565940819, 533470861, 191510652, 98758628, 966297064, 289095130, 277297970, 469628625, 788293500, 328851128, 613451788, 936544534, 176586284, 62642560, 71403401, 492996069, 532151949, 546888614, 462930373, 118754232, 227562075, 289190396, 464746954, 544692855, 494417695, 589257608, 82991518, 366164793, 175267372, 23539458, 375216401, 28785258, 636765616, 829772542, 799546834, 912024915, 145514842, 235595767, 877752650, 283920340, 543373943, 802264262, 372889612, 850522625, 671900687, 350386403, 202620501, 437098732, 380266893, 441784287, 707874467, 24616937, 798227922, 135215506, 907191596, 443862091, 412909727, 40007252, 555266369, 768794522, 845735930, 768475392, 811588759, 342799273, 349067491, 566661897, 463885518, 470015386, 492890654, 924677391, 294861231, 730741138, 942081432, 299014598, 213842495, 732754158, 411590815, 733768720, 680304612, 421188466, 998193104, 873089059, 68340229, 845700806, 344185820, 693910068, 381838285, 241119035, 468696474, 731280403, 537461184, 779697386, 54706238, 17661842, 290692910, 225734921, 908224130, 115851198, 408796690, 872301485, 678985700, 616590336, 19536043, 573802817, 115034633, 298959763, 34551359, 462560014, 422812809, 965329789, 922212382, 649233170, 729961491, 31035300, 675237517, 967146370, 82059367, 345578910, 996817111, 82704431, 321223153, 585390934, 175619009, 738808787, 677666788, 790919380, 729214097, 877615817, 323300957, 912101836, 139165026, 178404869, 434705235, 301946244, 491445797, 226594800, 647914258};
int ip[MX], v[62], pc;
LL S[MX];

void Init(int N) {
    for (int i = 2; i <= N; ++i) if (!ip[i]) {
        for (int j = i; j <= N; j += i) {
            if (j > i) ip[j] = 1;
            S[j] |= 1llu << pc;
        }
        v[pc++] = (i - 1) * qPow(i, Mod - 2) % Mod;
    }
}

const int MS = 1 << 20 | 7;
#define li (i << 1)
#define ri (i << 1 | 1)
#define len (r - l + 1)
#define mid ((l + r) >> 1)
#define now i, l, r
#define ls li, l, mid
#define rs ri, mid + 1, r
#define Root 1, 1, N
#define St int i, int l, int r

LL sum[MS], st[MS], t1[MS], t2[MS];

inline void P(St, LL v, LL s) {
    sum[i] = (sum[i] + len * v) % eM, st[i] |= s;
    t1[i] = (t1[i] + v) % eM, t2[i] |= s;
}
inline void Pd(St) {
    if (t1[i] || t2[i]) {
        P(ls, t1[i], t2[i]), P(rs, t1[i], t2[i]);
        t1[i] = t2[i] = 0;
    }
}

void Mdf(St, int a, int b, LL v, LL s) {
    if (r < a || b < l) return ;
    if (a <= l && r <= b) return P(now, v, s);
    Pd(now);
    Mdf(ls, a, b, v, s), Mdf(rs, a, b, v, s);
    sum[i] = (sum[li] + sum[ri]) % eM;
    st[i] = st[li] | st[ri];
}

pll Qur(St, int a, int b) {
    if (r < a || b < l) return pll(0llu, 0llu);
    if (a <= l && r <= b) return pll(sum[i], st[i]);
    Pd(now);
    pll p1 = Qur(ls, a, b), p2 = Qur(rs, a, b);
    return pll((p1.first + p2.first) % eM, p1.second | p2.second);
}

int N, Q;

int main() {
    int x;
    Init(300);
    scanf("%d%d", &N, &Q);
    for (int i = 1; i <= N; ++i) {
        scanf("%d", &x);
        Mdf(Root, i, i, E[x], S[x]);
    }
    for (int q = 1; q <= Q; ++q) {
        char opt[9]; int l, r;
        scanf("%s%d%d", opt, &l, &r);
        if (*opt == ‘T‘) {
            pll P = Qur(Root, l, r);
            LL Ans = qPow(G, P.first);
            for (int i = 0; i < pc; ++i)
                if (P.second >> i & 1) Ans = Ans * v[i] % Mod;
            printf("%llu\n", Ans);
        }
        else scanf("%d", &x), Mdf(Root, l, r, E[x], S[x]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/PinkRabbit/p/CF1114.html

时间: 2024-11-13 03:07:27

CodeForces Contest #1114: Round #538 (Div. 2)的相关文章

Codeforces Round #538 (Div. 2) (CF1114)

Codeforces Round #538 (Div. 2) (CF1114) ??今天昨天晚上的cf打的非常惨(仅代表淮中最低水平 ??先是一路缓慢地才A掉B,C,然后就开始杠D.于是写出了一个O(n^2)的线性dp,然后就wa6,调到结束.结束后发现完全看漏了两句话.噢,起始点!!! ??好吧然后算算自己有可能这一场要变成+0,反正在0左右. 结束后开始然后开始写D,顺便思考F.结果写完D发现A怎么fst了,然后...因为习惯于对相似的语句复制粘贴,有些东西没有改--三句话都在 -a!!!(

Codeforces Round #538 (Div. 2) D. Flood Fill 【区间dp || LPS (最长回文序列)】

任意门:http://codeforces.com/contest/1114/problem/D D. Flood Fill time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a line of nn colored squares in a row, numbered from 11 to nn f

Codeforces Round #538 (Div. 2) E 随机数生成

https://codeforces.com/contest/1114/problem/E 题意 交互题,需要去猜一个乱序的等差数列的首项和公差,你能问两种问题 1. 数列中有没有数比x大 2. 数列的第i项是什么 最多只能问60次 题解 首先用第一种问题+二分问出数列最大的数是多少,最多二十次 然后用第二种问题尽可能分散的询问第i项,然后将问出的数组排序,对相邻两个数的差求gcd 随机数生成链接 https://codeforces.com/blog/entry/61587 https://c

Codeforces Round #538 (Div. 2)

目录 Codeforces 1114 A.Got Any Grapes? B.Yet Another Array Partitioning Task C.Trailing Loves (or L'oeufs?) D.Flood Fill(区间DP) E.Arithmetic Progression(交互 二分 随机化) F.Please, another Queries on Array?(线段树 欧拉函数) Codeforces 1114 比赛链接 貌似最近平均难度最低的一场div2了...

[codeforces]Round #538 (Div. 2) F. Please, another Queries on Array?

题解:    $$  ans=F\left ( \prod _{i=l}^{r}a_i \right ) $$ $$ =(p_i-1){p_i}^{k_i-1}*.....*(p_j-1){p_j}^{k_j-1} $$ $$={p_i}^{k_i}*.....*{p_j}^{k_j}*(\frac{p_i-1}{p_i}*......*\frac{p_j-1}{p_j})  $$ 因为数据范围保证$ a_i\leq 300 $ 所以在这个范围内只有62个素因子  我们可以直接每一位对应一bit

[比赛] Codeforces Round #538 (Div. 2) solution (贪心,数学其他,二分,线段树)

已经写了100篇题解啦! link solution pdf #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read(){ int f=1,ans=0;char c; while(c<'0'||c>'9'){if(c=='-')f=-1;c

codeforces Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) B Guess the Permutation

B. Guess the Permutation Bob has a permutation of integers from 1 to n. Denote this permutation as p. The i-th element of p will be denoted as pi. For all pairs of distinct integers i, j between 1 and n, he wrote the number ai, j = min(pi, pj). He wr

codeforces Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) C. Constellation

C. Constellation Cat Noku has obtained a map of the night sky. On this map, he found a constellation with n stars numbered from 1 to n. For each i, thei-th star is located at coordinates (xi, yi). No two stars are located at the same position. In the

Codeforces 671B/Round #352(div.2) D.Robin Hood 二分

D. Robin Hood We all know the impressive story of Robin Hood. Robin Hood uses his archery skills and his wits to steal the money from rich, and return it to the poor. There are n citizens in Kekoland, each person has ci coins. Each day, Robin Hood wi