Description
LCJ报名参加了一个特殊的电视问答节目。这个节目共有n个问题,每回答正确1题,LCJ就会获得1分,而每当LCJ连续答对k题,那么他的现有得分乘以2,注意答对第K题后,是先加1分到总分中,再把总分乘以2,此时连续答对题目计数器会清零。现在LCJ成功对了m题,他想知道他的最小得分。因为这个数字可能很大,你只需要输出这个数对1,000,000,009取模的结果即可。
Input
仅一行,三个数n,m,k如题目描述。
2<=k<=n<=109,0<=m<=n。
Output
仅一行,一个数,LCJ的最小得分。
Sample Input
5 3 2
Sample Output
3
HINT
思路
每次答题得分的最小值一定是尽可能连续答对k−1题,如果还有可以答对的题,那么都放在前面的空缺中。注意这道题要快速幂,由于连续答对k∗m的得分为2(2(2(k)+k)+k...)=2m+2m−1+...+2=2m+1−2,因此答案加上这个值再减去重复求的值就好了。
代码
#include <cstdio>
const long long mo=1000000009ll;
long long n,m,k,ans;
long long quickpow(long long a,long long b,long long m)
{
int res=1;
while(b)
{
if(b&1)
{
res=(res*a)%m;
b--;
}
b/=2;
a=(a*a)%m;
}
return res;
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&k);
if(m<=n/k*(k-1))
{
ans=m;
}
else
{
ans=n/k*(k-1);
m-=n/k*(k-1);
if(m<=n%k)
{
ans+=m;
ans%=mo;
}
else
{
ans+=n%k;
ans%=mo;
m-=n%k;
ans+=m;
ans+=(quickpow(2ll,m+1,mo)-2-m)*k;
ans%=mo;
}
}
printf("%lld\n",ans);
return 0;
}