5871: 桃子的比赛
描述
桃子正在参加台院的一站到底比赛。比赛由n个连续的小问题组成,每回答正确一道题目就会获得1分。另外,这个比赛还有一个统计连续答案正确的计数器。当玩家回答正确时,这个计数器上的数字会增加1。反之,如果玩家回答错误,那么计数器将被重置,计数器上的数字将减少到0。如果在回答正确之后,计数器的值达到k,那么它将被重置,玩家已经获得的总分数将会翻倍。注意,在这种情况下,玩家会先获得1分,然后总分数翻倍。在游戏开始的时候,桃子的分数和计数器的值都为0。
桃子只记得他正确回答了m个问题。但他不记得回答问题的顺序。桃子想知道他的最低分数会是多少。帮助桃子计算相应分数对1000000009(109+9)取余后的结果。
输入
输入数据的第一行为测试用例的个数T (1≤T≤100)。
每组数据输入包含三个正整数n,m,k (2≤k≤n≤109 ,0≤m≤n)。
输出
每组数据输出一个整数,表示桃子的最低可能分数取余后的结果。
样例输入
2
5 3 2
5 4 2
样例输出
3
6
提示
对于第一个样例,桃子回答正确的是1,3,5,因为没有连续回答正确两道题目,所以分数不会翻倍。因此,结果是3。
对于第二个样例,桃子回答正确的是1,2,3,5, 回答对第2个问题后总分为2,翻倍后变成4,回答对第3个时,总分为5,回答对第5个问题时,总分为6。因此,结果为6。
看注释 ooo
#include<bits/stdc++.h> using namespace std; #define ll long long ll mod=1e9+9; ll quick(ll x,ll y) { ll sum=1; while(y) { if(y%2==1) sum=sum*x%mod; x=x*x%mod; y/=2; } return sum%mod; } int main() { ll t,i,j; ll n,m,k; scanf("%I64d",&t); while(t--) { scanf("%I64d%I64d%I64d",&n,&m,&k); ll zu=n/k;//组数 ll yu=n%k;//余下来的 ll maxx=zu*(k-1)+yu;//隔一个放(k-1)个 maxx就是可以放的最大数 if(maxx>=m) printf("%I64d\n",m);//直接输出 else//否则 要快速幂 for会超时 { ll zuu=m-maxx;//翻倍的组数 ll q=((k%mod)*quick(2,zuu+1)-2*k+mod)%mod;//算翻倍的 列个k=2,=3的情况就可以找到规律了 :k*2^(zuu+1)-2*k (attention:要+个mod 不然-2*k的时候可能会负数掉) ll ydw=q+(zu-zuu)*(k-1)%mod+yu;//加上没翻倍的以及余下来的 printf("%I64d\n",ydw%mod); } } }