原题地址: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)
注意:要特判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;
}