2024省选联测12

A. 硬币

给定 \(n\),在满足 \(x\times y = n^2+1\)\(x,y\ge2\) 的前提下,最大化 \(x+y\)

从后向前扫描序列,第 \(i\) 个数被扫到时为 \(p\)\(p\) 为质数或者为 \(1\)。第 \(i+kp,k\in\mathbb{Z}\) 个数仍然是 \(p\) 的倍数。

因为

\[i^2+1\equiv 0\mod p \]

所以

\[(i+kp)^2+1\equiv i^2+1+2ikp+k^2p^2\equiv0\mod p \]

举例如下

\[\begin{aligned} 2 && 5&& 10&&17&& 26 &&37&& 50&& 65&& 82&& 101&& 122&& 145&& 170&&197&&226\\ 1 &&5&& 5&& 17&& 13 &&37 &&25 &&65 &&41&&101 &&61 &&145 &&85&&197&&113\\ 1 &&1&&5&&17&&13&&37&&5&&65&&41&&101&&61&&29&&85&&197&&113\\ 1&&1&&1&&17&&13&&37&&5&&13&&41&&101&&61&&29&&17&&197&&113\\ \end{aligned} \]

点击查看代码
for(int i = 1; i <= m; ++ i) p[i] = i * i + 1, a[i] = 1e18;

for(int i = 1; i <= m; ++ i)
{
    if(p[i] == 1) continue;

    a[i] = min(a[i], p[i]);

    for(int j = i + p[i]; j <= m; j += p[i])
    {
        a[j] = min(a[j], p[i]);
        while(p[j] % p[i] == 0) p[j] /= p[i];
    }
}

B. 猜数

你要从数集 \(1,2,\cdot\cdot\cdot ,n\) 中猜一个数,每次提问一个数 \(x\),交互库会返回大于、小于或等于,代价为 \(x\)
\(C(n)\) 表示在最优策略下的总成本。最优策略指的是在最坏情况下最小化总成本的策略。求 \(\sum_{i=1}^n C(n)\)

\(f_{i,j}\) 表示从 \([i,j]\) 中猜数的成本。

\[f_{i,j}=\min(f_{i,j},\max(f_{i,k-1},f_{k+1,j})+k) \]

从左向右枚举 \(j\),再从 \(j\) 向前枚举 \(i\),维护一个分界点 \(K_0\)

\(k< K_0\) 时,\(f_{i,k-1}< f_{k+1,j}\)\(K_0\) 逐渐减小,可使用单调队列维护 \(f_{k+1,j}\) 最小值。

\(k\ge K_0\) 时,\(f_{i,k-1}\ge f_{k+1,j}\)。最小值为 \(f_{i,K_0-1}\)

又发现 \(K_0\) 取到的地方举例右端点不远,大概为 \(\dfrac{len}{\log len}\)

这样状态就少了很多,再滚一下就好了。

点击查看代码
int dp(int l, int r) {if(l > r) return 0; return f[p[r]][r - l + 1];}

for(int i = 1; i <= n; ++ i) p[i] = i % 4000 + 1;

for(int r = 2; r <= n; ++ r)
{
    int k = r - 1, head = 1, tail = 0; g[r] = 1e18;
    for(int l = r - 1; l >= max(1ll, r - 3999); -- l)
    {
        while(dp(l, k - 1) > dp(k + 1, r)) -- k;

        while(head <= tail && q[head] > k) ++ head;
        while(head <= tail && q[tail] + dp(q[tail] + 1, r) > l + dp(l + 1, r)) -- tail;
        q[++tail] = l;
        f[p[r]][r - l + 1] = min(dp(l, k) + k + 1, q[head] + dp(q[head] + 1, r));
        g[r] = min(g[r], max(g[l - 2], dp(l, r)) + l - 1);
    }
}

    for(int i = 1; i <= n; ++ i) ans += g[i];

C. 卡片

你有若干张编号为 \(1\)\(n\) 的卡片,和 \(m\) 包可以无限开的卡包,你可以以任意顺序执行任意多次以下操作:

  • \(2i\) 张编号为 \(i\) 的卡片换成一张编号为 \(i\bmod n+1\)的卡片。
  • 选择一个卡包打开并获得其中的所有卡片。
    你希望你拥有的卡片张数尽可能的少,求出经过任意多次操作后你拥有的卡片的最小张数。

原题:Die Siedler

posted @ 2024-01-17 22:12  Estelle_N  阅读(32)  评论(0编辑  收藏  举报