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答对第1、3、5题可以获得最低分3分;
样例2只答错第4题,可以获得最低分6分。
【数据范围】
对于30%的数据,n,m,k<=10
对于60%的数据,n,m,k<=1000
对于100%的数据,1<=k<=n<=10^9,0<=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 }

浙公网安备 33010602011771号