5871: 桃子的比赛

描述

桃子正在参加台院的一站到底比赛。比赛由n个连续的小问题组成,每回答正确一道题目就会获得1分。另外,这个比赛还有一个统计连续答案正确的计数器。当玩家回答正确时,这个计数器上的数字会增加1。反之,如果玩家回答错误,那么计数器将被重置,计数器上的数字将减少到0。如果在回答正确之后,计数器的值达到k,那么它将被重置,玩家已经获得的总分数将会翻倍。注意,在这种情况下,玩家会先获得1分,然后总分数翻倍。在游戏开始的时候,桃子的分数和计数器的值都为0。

桃子只记得他正确回答了m个问题。但他不记得回答问题的顺序。桃子想知道他的最低分数会是多少。帮助桃子计算相应分数对1000000009(109+9)取余后的结果。

输入

输入数据的第一行为测试用例的个数T (1≤T≤100)。

每组数据输入包含三个正整数n,m,k (2≤k≤n≤10,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);
        }
    }
}
View Code

 

posted @ 2019-07-02 17:50  -第4题-  阅读(294)  评论(0编辑  收藏  举报