题意很清晰,这种题,我们当然还是有两种方法来做啦
方法一:找规律
读完题我们来看样例,通过样例一已我们大概可以看出,答案或许是(n*2^{k+1})
肯定不能这么简单对吧,那就来看样例二,难道答案是(n*2^{k+1}-k)或者是(n*2^{k+1}-2^{k-1})也有可能是(n*2^{k+1}-2^k+1)
通过样例三可得,答案是(n*2^{k+1}-2^k+1)
方法二:数学证明
每个月都是乘2,所以第i个月取走一个对第j个月的影响就是(2^{j-i}(i<j))
那么每个月都会对最后一个月产生影响,影响总和是$ sum _ {i=0} ^ {k-1} 2^i $,也就是(2^k-1)
这是负的影响,正的影响很容易算,就是(n*2^{k+1})
说白了,每个月要么直接乘二,要么-1再乘二,我们把这个-1提出来,就分成了上面所说的正贡献和负贡献
千万别忘了特判等于零,还有直接乘会爆long long
下面放代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
#define ll long long
#define gc getchar
#define mo 1000000007
using namespace std;
inline ll read(){
ll a=0;int f=0;char p=gc();
while(!isdigit(p)){f|=p=='-';p=gc();}
while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
return f?-a:a;
}
ll n,k,k1,e=2,sum=1;
inline ll cheng(ll a,ll b){
ll sum=0;
while(b){
if(b&1)sum=(sum+a)%mo;
a=(a<<1)%mo;b>>=1;
}
return sum;
}
int main(){
n=read();k1=k=read();++k;
if(n==0){
puts("0");
return 0;
}k%=mo-1;
while(k){
if(k&1)n=cheng(n,e)%mo;
e=cheng(e,e)%mo;k>>=1;
}e=2;k1%=mo-1;
while(k1){
if(k1&1)sum=cheng(sum,e)%mo;
e=cheng(e,e)%mo;k1>>=1;
}
--sum;if(sum<0)sum+=mo;
printf("%lld
",((n-sum)%mo+mo)%mo);
return 0;
}
不要抄代码哦