Codeforces Round #489 (Div. 2) C. Nastya and a Wardrobe (数学推公式)

原题地址:http://codeforces.com/contest/992/problem/C

题意:给出一个n,k,表示初始拥有n元钱,时间为k年。然后每一年你都有50%几率金钱翻倍,还有50%几率金钱翻倍后减1.然后k年之后,你金钱会100%翻倍。问你k年后,可以期望拥有多少钱。

思路:可以说是推公式找规律了。
现在假设你有n元钱。(下面的结果都是先假设k年后不翻倍的)
那么1年后,你期望拥有的钱是 1/2*(2n+2n-1)
两年后的钱是 1/2*1/2*(4n+4n-1+4n-2+4n-3)
三年后钱是1/2*1/2*1/2*(8n+8n-1+8n-2+8n-3+8n-4+8n-5+8n-6+8n-7)

由此可知最后结果应该是这样一个公式(最后乘了2)
2 k + 1 n ( 2 k 1 )

注意:要特判n==0 这种情况

不用快乘的版本

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll n, k;
ll quickpow(ll base, ll n) {//快速幂
    ll res = 1;

    while(n) {
        if(n & 1) res = res * base % mod;
        n >>= 1;
        base = base * base % mod;
    }
    return res;
}

int main() {
    cin >> n >> k;
    if(n == 0) {
        cout << "0" << endl;
        return 0;
    }
        n=n%mod;//要先对n取模,不然会爆long long 
  ll ans=((quickpow(2,k+1)*n%mod-(quickpow(2,k)-1+mod)%mod)%mod+mod)%mod;
         ans=(ans+mod)%mod;//因为取模之后前面可能会比后面小
         cout<<ans<<endl;
    return 0;
}

快乘的版本

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll n, k;
ll quickpow(ll base, ll n) {//快速幂
    ll res = 1;

    while(n) {
        if(n & 1) res = res * base % mod;
        n >>= 1;
        base = base * base % mod;
    }
    return res;
}
ll quickmul(ll a, ll b) {//快乘
    ll res = 0;
    while(b) {
        if(b & 1) res = (res + a) % mod;
        b >>= 1;
        a = (a + a) % mod;
    }
    return res;
}
int main() {
    cin >> n >> k;
    if(n == 0) {
        cout << "0" << endl;
        return 0;
    }
        n=n%mod;//如果用了快乘的话,这个加不加就无所谓了,因乘法中间不会爆long long 
    ll ans = (quickmul(quickpow(2, k + 1), n) % mod) - (quickpow(2, k) - 1 + mod) % mod;
        ans=(ans+mod)%mod;
         cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/80740797