题意简述
yzh 在一个特殊的日子里,送给你了 \(n\) 颗具有魔法的石子!你当然知道这是她为你准备的惊喜。她偷偷告诉你,为了使它们的魔法被释放出来,只有把这些石子分成若干堆,并且每一堆石子个数都能表示成 \(3x^2-3x+1\) 的形式,其中 yzh 希望让 \(x > 1\)。以你的聪明才智,不久就想到了划分的方法。并且你自信地说:“无论你给我多少颗石子,我都可以找到一种划分方案!”。这时她又凑到你耳边说,你需要让堆数最少,这样魔法的力量会更加集中,发挥出最美丽的效果。这对你来说还不是小菜一碟?你思索了一会,说道:“我编写一段程序就可以!”
\(n \leq 3 \times 10^{11}\),多测,\(T \leq 10^3\)。
题目分析
经过背包打表知道,这题答案不多,最多才 \(8\),显然需要大力分讨。
记 \(f(x) = 3x^2-3x+1\)。手玩一会不难发现,\(f(x + 1) - f(x) = 6x\),这是一个美妙的性质。不妨列出来:
\[\begin{aligned} f(1) &= 1 + 6 \times (0) \\ f(2) &= 1 + 6 \times (0 + 1) \\ f(3) &= 1 + 6 \times (0 + 1 + 2) \\ f(4) &= 1 + 6 \times (0 + 1 + 2 + 3) \\ &\ \ \vdots \\ f(x) &= 1 + 6 \times \Big (0 + 1 + \cdots + (x - 1) \Big) \end{aligned} \]一定存在一种划分方案将在最后说明。假设我们将 \(n\) 分成了 \(m\) 份,那么我们的 \(n\) 就会可以被表示成 \(m + 6 \times \sum \limits _ {i = 1} ^ m \Big( 0 + 1 + \cdots + (x_i - 1) \Big )\)。
如果 \(6 \mid n\),说明 \(6 \mid m\),结合我们得出的 \(m \leq 8\),可知此时必有 \(m = 6\)。接下来尝试构造,证明一定存在这样的方案。
此时有 \(\cfrac{n - m}{6} = \sum \limits _ {i = 1} ^ 6 \Big( 0 + 1 + \cdots + (x_i - 1) \Big )\)。我们只需要说明,用后面的求和能表示出任意给定的 \(w \geq 0\)。事实上,我们有一个更强的结论:能使用不超过 \(3\) 个形如 \(1 + \cdots + x\) 的数表示出任意自然数,至于剩下的数,填 \(x_i = 1\) 即可。这正是根据了「费马多边形数定理」,原定理为:任意正数可以表示为不超过 \(n\) 个 \(n\) 边形数的和。
Fermat polygonal number theorem [1]
every positive integer is a sum of at most n n-gonal numbers.
所以,当 \(6 \mid n\) 时,我们有答案为 \(6\),那对于其他的 \(n\) 呢?在 \(\bmod 6\) 之后会有什么规律吗?
我们关注 \(n \equiv 1 \pmod 6\) 的情况,此时如果 \(n\) 恰好能被表示为一个 \(f(x)\),答案就为 \(1\)。这个判断就是解个简单的一元二次方程。否则,由于 \(m \equiv 1 \pmod 6\),此时必有 \(m = 7\),并且方案也是存在的。考虑任意选出一个小于 \(n\) 的 \(f(x)\),\(n\) 减去它之后就是 \(6 \mid n\) 的情况。
类似考虑 \(n \equiv 2 \pmod 6\) 的情况。如果 \(n\) 能被表示成两个 \(f(x)\) 的和,答案就是 \(2\),否则为 \(8\)。发现,由于 \(n \leq 3 \times 10^{11}\),所以 \(\max \left \{ x \mid f(x) \leq 3 \times 10^{11} \right \} = 316228\),我们完全可以枚举其中一个 \(f(x)\),然后看看另一个 \(f(x)\) 是否存在即可。
对于 \(n \bmod 6 > 2\) 的情况也是一样的吗?并不是。还记得我们一开始讨论的 \(6 \mid n\) 吗?我们此时已经有 \(n \bmod 6 \geq 3\),也就是说,一定能够构造出方案来了。此时答案就是 \(n \bmod 6\)。
我们同时证明了原问题一定有解。
综上,我们可以把答案表示为:
\[ans = \left\{ \begin{matrix} 6 & \text{ if } n \equiv 0 \pmod 6 \\ 1 & \text{ if } n \equiv 1 \pmod 6 \ \text{and} \ \exists x, n = f(x) \\ 7 & \text{ if } n \equiv 1 \pmod 6 \ \text{and} \ \forall x, n \neq f(x) \\ 2 & \text{ if } n \equiv 2 \pmod 6 \ \text{and} \ \exists x,y, n = f(x) + f(y) \\ 8 & \text{ if } n \equiv 2 \pmod 6 \ \text{and} \ \forall x,y, n \neq f(x) + f(y) \\ n \bmod 6 & \text{ if } n \bmod 6 \in [3, 5] \end{matrix}\right. \]代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
long long n;
template <typename T>
inline long long f(T x) {
return 3ll * x * x - 3ll * x + 1;
}
inline bool check(long long x) {
long long y = (3 + sqrt(12 * x - 3)) / 6 + 1e-20;
return f(y) == x;
}
void solve() {
scanf("%lld", &n);
int tmp = n % 6;
if (!tmp) return puts("6"), void();
if (tmp > 2) return printf("%d\n", tmp), void();
if (tmp == 1) return puts(check(n) ? "1" : "7"), void();
for (int i = 1; f(i) <= n / 2; ++i)
if (check(n - f(i))) return puts("2"), void();
puts("8");
}
signed main() {
int t; scanf("%d", &t);
while (t--) solve();
return 0;
}