当前位置: 代码迷 >> 综合 >> 3的幂的和 51Nod - 1013 (等比数列求和 + 快速幂 + 乘法逆元)
  详细解决方案

3的幂的和 51Nod - 1013 (等比数列求和 + 快速幂 + 乘法逆元)

热度:98   发布时间:2023-12-12 14:20:08.0

求:3^0 + 3^1 +…+ 3^(N) mod 1000000007

Input
输入一个数N(0 <= N <= 10^9)

Output
输出:计算结果

Input示例
3

Output示例
40

这道题很明显需要用到快速求幂,但是简单的快速求幂无法满足这道题的要求,如何求和是一个很重要的问题,求和有一个简单的方法,也有一个复杂的,先说复杂的,虽然复杂却容易理解。

#include <stdio.h>
#define _MOD 1000000007
typedef long long ll;ll c;//快速求幂
ll power(ll a, ll b)
{ll ans = 1;while (b){if (b & 1){ans = (ans * a) % _MOD;b--;}b >>= 1;a = (a * a) % _MOD;}return ans;
}ll sum(ll a, ll k)
{if (k == 1){return a;}c = sum(a, k >> 1); //前k/2个次幂的和//ans等于前k/2个次幂的和加上接着的k/2个次幂的和(前k/2个次幂的和乘以第k/2个数的次幂)ll ans = (c + c * power(a, (k >> 1))) % _MOD;//加上最后一个奇数次方值if (k & 1){ans = (ans + power(a, k)) % _MOD;}return ans;
}int main()
{ll n;scanf("%lld", &n);printf("%lld\n", ((sum(3, n) % _MOD)) + 1);return 0;
}

这里的求和函数有着快速求幂的思想,结合了递归来实现了幂的求得,有点意思的题。

另外还有一个很简单很简单的方法,只用一行就可以替代去求和的过程,那就是用到逆元,然而像我这样的数学早已九九归一的人,已经不知道怎么去理解这行代码中蕴含的数学理论,只是知道,把它当作公式一样去记住就好了,让我去理解推一下这个公式,已经不是我现在一时半会儿能做到的,数学家们通过几十年的研究才研究出来的东西,我这数学忘完了的人就无力去推算了,证明公式的正确性的事已经不是我的事情了,所以这里只是看看,记住公式,以后争取用到就好了。

#include<stdio.h>
#define mod 1000000007
typedef long long ll;ll mod_pow(ll x,ll n)
{ll res = 1;while(n > 0){if(n & 1)res = res * x % mod;x = x * x % mod;n >>= 1;}return res;
}int main()
{ll n, ans;scanf("%lld", &n);n++;ans = (mod_pow(3, n) - 1) * 500000004 % mod;    //求2的逆元即可.因为2 * ? = 1 (mod 1000000007) ? = 500000004printf("%lld", ans);return 0;
}

总结下来就是先求3的n+1次幂,减去一后,乘以2与mod的逆元,最后再取一下模即可。感觉十分不可思议,根本想不通这个解法的内在原理,但是只知道其具有可行性,所以,记住这个方法,记住这个公式,就已经不错了。