Update
- \(\texttt{2021.11.27}\) 修复了代码中的 \(10000\) 写成 \(n\) 的错误。
Content
一个家庭住在一个胡同里面,门牌号从 \(1\) 开始编号。其余门牌号的和减去这个家庭的门牌号的两倍恰好等于 \(n\),求这个家庭的门牌号和胡同的门牌号总数。
数据范围:\(n<10^5\)。
Solution
如果设胡同的门牌号总数为 \(m\),并设这个家庭的门牌号为 \(k\),则由题意可得(其中 \([i\neq k]\) 表示如果 \(i\neq k\),则这个值为 \(1\),否则为 \(0\)):
\[\sum\limits_{i=1}^mi[i\neq k]-2k=n \]如果我们把这个 \(\sum\limits_{i=1}^mi[i\neq k]\) 转化一下:
\[\begin{aligned}1+2+\dots+k-1+k+1+\dots+m&=1+2+\dots+m-k\\&=\sum\limits_{i=1}^mi-k\end{aligned} \]所以:
\[\begin{aligned}\sum\limits_{i=1}^mi-k-2k&=n\\3k&=\sum\limits_{i=1}^mi-n\\k&=\dfrac{\sum\limits_{i=1}^mi-n}{3}\end{aligned} \]用等差数列求和公式将 \(\sum\limits_{i=1}^mi\) 转化为 \(\dfrac{m(m+1)}2\) 可得:
\[k=\dfrac{\dfrac{m(m+1)}2-n}3 \]因此,我们可以枚举 \(m\),然后是否满足以下两个条件:
- \(\dfrac{m(m+1)}2>n\)。
- \(3\mid(\dfrac{m(m+1)}2-n)\)(表示 \(3\) 能整除 \(\dfrac{m(m+1)}2-n\))。
可以发现,一旦满足了以上两个条件,\(m\) 此时的值依然很小,因此这样枚举是可以通过这道题的。
Code
#include <cstdio>
using namespace std;
int main() {
int n; scanf("%d", &n);
for(int i = 1; i <= 10000; ++i) {
int ans = i * (i + 1) / 2;
if(ans > n && !((ans - n) % 3)) {printf("%d %d", (ans - n) / 3, i); return 0;}
}
return 0;
}