Test20200608

虚伪之气太盛!

T1   答题比赛

快速幂

【问题描述】

YYH报名参加了一个特殊的电视问答节目。这个节目共有n个问题,每回答正确1题,YYH就会获得1分,而每当YYH连续答对k题,那么他的现有得分乘以2,注意答对第k题后,是先加1分到总分中,再把总分乘以2,此时连续答对题目计数器会清零。现在YYH成功对了m题,他想知道他的最小得分。因为这个数字可能很大,你只需要输出这个数对1,000,000,009取模的结果即可。

【输入格式

仅一行,三个数n,m,k如题目描述。

【输出格式

仅一行,一个数,YYH的最小得分。

【输入输出样例1

exam.in

exam.out

5 3 2

3

 

【输入输出样例2 

exam.in

exam.out

5 4 2

6


【样例解释】

样例1答对第135题可以获得最低分3分;

样例2只答错第4题,可以获得最低分6分。

【数据范围

    对于30%的数据,n,m,k<=10

对于60%的数据,n,m,k<=1000

对于100%的数据,1<=k<=n<=10^90<=m<=n

优先放k-1格空一格,然后从前往后放,用等比数列求前n项和求出连续段的分数通式,再用快速幂计算

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define mod 1000000009
 4 #define ll long long
 5 inline int read()
 6 {
 7     int x=0;char c=getchar();
 8     for(;!isdigit(c);c=getchar());
 9     for(;isdigit(c);c=getchar()) x=x*10+c-'0';
10     return x;
11 }
12 ll n,m,k,flag,res,sum=0;
13 ll poww(ll a,ll b)
14 {
15     ll ans=1;
16     while(b>0)
17     {
18         if(b&1)
19         {
20             ans=ans*a%mod;
21         }
22         a=a*a%mod;
23         b>>=1;
24     }
25     return ans;
26 }
27 int main()
28 {
29     freopen("exam.in","r",stdin);
30     freopen("exam.out","w",stdout);
31     cin>>n>>m>>k;
32     flag=n/k*(k-1)-n/k*k+n;
33     if(flag>=m) 
34     {
35         printf("%lld\n",m);
36         return 0;
37     } 
38     res=m-flag;
39     sum=k*poww(2,res+1)-k*2;
40     sum+=(n/k-res)*(k-1)-n/k*k+n;
41     sum%=mod;
42     printf("%lld\n",sum);
43     return 0;
44 }

 

posted @ 2020-06-08 08:13  SuYongkang  阅读(146)  评论(0)    收藏  举报