51Nod 1013 3的幂的和 快速幂 | 乘法逆元 | 递归求和公式

 

 

1.乘法逆元

直接使用等比数列求和公式,注意使用乘法逆元

---严谨,失细节毁所有

#include "bits/stdc++.h"
using namespace std;
#define rep(i, s, n) for(int i=s;i<n;i++)
#define MOD 1000000007
#define LL long long
const int N=10010;
LL quick_pow(LL a,LL b)
{
    LL ans=1;
    while(b>0){
        if(b&1){
            ans=ans*a%MOD;
        }
        b>>=1;
        a=a*a%MOD;
    }
    return ans;
}
int main()
{
    int n;
    LL sum;
    while(~scanf("%d",&n)){
        sum= (quick_pow(3, n+1) - 1) * 500000004 % MOD;
    ///求2的逆元即可.因为2 * ? = 1 (mod 1000000007)  ? = 500000004
    ///而不是简单的(quick_pow(3, n+1) - 1) /2 % mod;遇到mod /将/转变为*除数的逆元
        printf("%lld\n",sum);
    }
    return 0;
}

 扩展欧几里得求乘法逆元

const int mod=1000000007;
long long inv(long long a)
{
    if(a==1)
        return 1;
    return inv(mod%a)*(mod-mod/a)%mod;
}
int main()
{
    cout<<inv(2)<<endl;
}

 

 2.思维,构造递归求和公式

 

#include "bits/stdc++.h"
using namespace std;
#define rep(i, s, n) for(int i=s;i<n;i++)
#define _MOD 1000000007
#define ll long long
const int N=10010;
ll c;
ll power(ll a, ll b)
{
    ll ans = 1;
    while (b)
    {
        if (b & 1)
        {
            ans = (ans * a) % _MOD;
        }
        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;
}

 带入 4、5试一下,递归的巧妙

 

参考:http://blog.csdn.net/f_zyj/article/details/51231838

 

posted @ 2017-10-07 11:36  kimsimple  阅读(431)  评论(0编辑  收藏  举报