题干:有N个人在传球。它从第一个人开始,每次拿到球的人都要把球传给另一个人。那么传球M次后,球又被传给第一个人的情况有多少种呢?
数据范围:包括两个整数N和M, N∈[2,9],M∈[1,15]。
很多新手第一次拿到这道题都都直接上手去做,认为这是一道简单题,再一看n和m的取值范围,就觉得这题就是送分题,就开始模拟,其实到最后都ac不了这道题。
其实这道题不是简单题,是一道数学结论题。
题干给的数据很巧妙,在int的取值范围之内,而不必使用longlong,这就是这道题更加容易了。
还是照旧,我们先看核心代码
int main()
{
int n, m, sum = 0;
cin >> n >> m;
if (m % 2 == 1)
{
sum = ((int)pow(n - 1,m) - n + 1) / n;
}
else
sum = ((int)pow(n - 1,m) + n - 1) / n;
printf("%d", sum);
return 0;
}
没错就是这么简单。不到十行的代码!!!
那么我们接下来看看这道题的结论的数学分析吧!
数学分析:
不妨设F[k]为球最后传给第k个人的情况数。那么我们的所求量就是F[1].
显然球最后传给第2到第N个人的概率相同,即F[2]=F[3]=...=F[N]。
所以所有总情况的数学表达式:
F[1]+F[2]+F[3]+...+F[N]=(N-1)^M
即F[1]+(N-1)*F[2]=(N-1)^M
那么我们的当前的问题只需求解出F[2]即可依靠方程解出F[1]。
我们接着分析。
1.先讨论1,2不持球的情况。
球一旦传给第3到第N个人,则球最后传给前两个人的概率相同。(因为我要利用F[1]写出F[2]的表达式,所以只提到1,2两个人)
即球在传给第3个人到第N个人的情况中,球传给前两个人的情况数是相同的(同上)
2.在讨论1,2互传的情况。
此时球没给到第三个到和N个人的手中时,即1,2两人互传的情况。
此时:
若M为奇数,则最后传给第2个人
若M为偶数,则最后传给第1个人
即F[2]=F[1]+1(M为奇数)
F[2]=F[1]-1(M为偶数)
带入方程求解有 F[1]=((N-1)^M-N+1)/N(M为奇数)
F[1]=((N-1)^M+N-1)/N(M为偶数)
我们再看一遍代码:
int main()
{
int n, m, sum = 0;
cin >> n >> m;
if (m % 2 == 1)
{
sum = ((int)pow(n - 1,m) - n + 1) / n;
}
else
sum = ((int)pow(n - 1,m) + n - 1) / n;
printf("%d", sum);
return 0;
}
怎么样你明白了么?