LCJ報名參加了一個特殊的電視問答節目。這個節目共有n個問題,每回答正確1題,LCJ就會獲得1分,而每當LCJ連續答對k題,那麼他的現有得分乘以2,注意答對第K題後,是先加1分到總分中,再把總分乘以2,此時連續答對題目計數器會清零。現在LCJ成功對了m題,他想知道他的最小得分。因爲這個數字可能很大,你只需要輸出這個數對1,000,000,009取模的結果即可。
輸入格式:
僅一行,三個數n,m,k如題目描述。
輸出格式:
僅一行,一個數,LCJ的最小得分。
樣例輸入:
樣例一 5 3 2 樣例二 5 4 2
樣例輸出:
樣例一 3 樣例二 6
數據範圍:
對於30%的數據,n,m,k<=10
對於60%的數據,n,m,k<=1000
對於100%的數據,2<=k<=n<=10^9,0<=m<=n
這大概是我爲數不多的一遍ac的數學題。。。。
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include<queue>
#include <vector>
#define pb push_back
#define forup(i,a,b) for(int i=(a);i<=(b);i++)
#define fordown(i,a,b) for(int i=(a);i>=(b);i--)
#define maxn 100005
#define maxm 100005
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template<class T> inline
void read(T& num){ num = 0; bool f = true;char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();} while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();} num = f ? num: -num; }
int out[100];
template<class T> inline
void write(T x,char ch){ if (x==0) {putchar('0'); putchar(ch); return;} if (x<0) {putchar('-'); x=-x;}int num=0; while (x){ out[num++]=(x%10); x=x/10;} fordown(i,num-1,0) putchar(out[i]+'0'); putchar(ch); }
/*==================split line==================*/
int n,m,k;
const int mod =1e9+9;
ll mi(int p,int ci)
{ if(ci==0) return 1ll;if(ci==1) return p%mod; ll x=mi(p,ci>>1);x=(x*x)%mod;if(ci%2==1) x=(x*p)%mod;return x%mod;}
int main()
{ cin>>n>>m>>k;
if(n==m)
{ int x=n/k,y=n%k;
ll p=mi(2,x+1)%mod;
p=(p-2+mod)%mod; p=p*k%mod;
p=(p+y)%mod;
cout<<p;
return 0;
}
int t=n/k,p=n%k;//t有幾個抽屜
if(m<=p) {cout<<m;return 0;}
m=m-p;
ll left=m-(k-1)*t;
if(left<=0){cout<<(m+p)%mod;return 0;}
ll ans=(((mi(2,left+1)-2+mod)%mod)*k)%mod;ans=ans%mod;
cout<<(ans+p+(t-left)*(k-1))%mod;
return 0;
}