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