P10090 [ROIR 2022] 幼儿园的新年 (Day 2) 题解

P10090 [ROIR 2022] 幼儿园的新年 (Day 2) 题解

\(kn(k\in\mathbb{N}_+)\)\(n\) 的倍数。

首先,我们确定 \(kn\) 的取值范围,显然 \(kn\le a+b\)

此时 \(kn\) 的枚举范围已经确定,然后该考虑什么样的 \((x,y)\) 的可以对答案产生贡献。不难发现 \((x,y)\) 的取法受到 \(a,b\)\(n\) 之间大小关系的影响,接下来我们便具体探讨其中的关系。

以下若无特殊说明,默认 \(a\le b,0\le x\le a,0\le y\le b\)

先从简单的入手,只考虑单个 \(kn\) 对答案的贡献,我们可分为以下几种情况:

  1. \(kn\le a,b\)
    由于 \(kn\le a,b\),则必然有 \(x\)\(y\) 满足 \(x=kn\)\(y=kn\),便有以下几种可能:

    \[\begin{aligned} 0+y&=kn\\ 1+(y-1)&=kn\\ &\vdots\\ x+0&=kn \end{aligned} \]

    那么此时便对答案有 \((x-0)+1=(y-0)+1=kn+1\) 的贡献。
  2. \(a<kn\le b\)
    由于此时 \(a<kn\),所以无论 \(x\) 怎么取,仍然不会超出 \(kn\) 的范围,那么 \(x\) 的范围便固定在 \([0,a]\) 中,那么 \(y\) 的范围也随之固定,也就有以下几种可能:

    \[\begin{aligned} 0+y&=kn\\ 1+(y-1)&=kn\\ &\vdots\\ a+(y-a)&=kn \end{aligned} \]

    那么此时对答案有 \((a-0)+1=a+1\) 的贡献。
  3. \(a,b<kn\)
    同理,请自己尝试像上面两种情况推导后,得出以下几种可能:

    \[\begin{aligned} (kn-b)+b&=kn\\ (kn-b+1)+(b-1)&=kn\\ &\vdots\\ a+(kn-a)&=kn \end{aligned} \]

    那么此时对答案有 \(a-(kn-b)+1=a+b-kn+1\) 的贡献。

此时我们对单个 \(kn\) 考虑完毕,再考虑多个 \(kn\) 对答案的贡献。

现在的变量又多了一个 \(k\),由于 \(k\) 的变化导致 \(kn\)\(a,b\) 的大小关系不定,所以我们要确定好在上面三种情况中 \(k\) 各自的取值范围。

  1. \(kn\le a,b\)
    \(m_1=\left\lfloor\frac{a}{n}\right\rfloor\),则 \(k\in[1,m_1]\) 总的贡献为:

    \[\sum_{k=1}^{m_1}\left(i\times n+1\right)=\sum_{k=1}^{m_1}(i\times n)+m_1 \]

    利用求和公式即可化简为:

    \[\frac{n(m_1+1)\times m_1}{2}+m_1 \]

  2. \(a<kn\le b\)
    \(m_2=\left\lfloor\frac{b}{n}\right\rfloor\),则 \(k\in(m_1,m_2]\)

    不难发现,此条件下 \(k\) 的变化对最终贡献没有影响,所以贡献为:

    \[\sum_{i=m_1+1}^{m_2}a+1=(m_2-m_1)\times(a+1) \]

  3. \(a,b<kn\)
    \(m_3=\left\lfloor\frac{a+b}{n}\right\rfloor\),则 \(k\in(m_2,m_3]\),贡献为:

    \[\begin{aligned} &\sum_{i=m_2+1}^{m_3}(a+b-i\times n+1)\\ =&(m_3-m_2)\times(a+b+1)-\sum_{i=m_2+1}^{m_3}(i\times n)\\ =&(m_3-m_2)\times(a+b+1)-\left(\sum_{i=1}^{m_3}(i\times n)-\sum_{i=1}^{m_2}(i\times n)\right)\\ =&(m_3-m_2)\times(a+b+1)-\left(\frac{n(m_2+1)\times m_2}{2}-\frac{n(m_3+1)\times m_3}{2}\right) \end{aligned} \]

这样,我们就得出了最终的公式,用代码实现即可,时间复杂度 \(\mathcal{O}(t)\)

代码

$\text{Code}$
#include <bits/stdc++.h>

using namespace std;

int t, n, a, b, m1, m2, m3;
long long ans; // 别忘了 long long

template <typename type>
void read(type &res) {
    type x = 0, f = 1;
    char c = getchar();
    for (; c < 48 || c > 57; c = getchar()) if (c == '-') f = ~f + 1;
    for (; c > 47 && c < 58; c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    res = f * x;
}

int main() {
	read(t);
	while (t--) {
		ans = 0;
		read(n), read(a), read(b);
      // 把上面的公式翻译成代码就行了
		if (a > b) swap(a, b);
		m1 = a / n;
		m2 = b / n;
		m3 = (a + b) / n;
      // 下面也要开 long long
		ans += ((1ll * n * (m1 + 1) * m1) >> 1) + m1;
		ans += 1ll * (m2 - m1) * (a + 1);
		ans += 1ll * (m3 - m2) * (a + b + 1) - (((1ll * n * (m3 + 1) * m3) >> 1) - ((1ll * n * (m2 + 1) * m2) >> 1));
		printf("%lld\n", ans);
	}
    return 0;
}
posted @ 2025-06-21 19:49  ZaleClover  阅读(43)  评论(0)    收藏  举报