CF337C - Quiz

 1 /*题目大意,给出n道题,假设答对了m道题,求最小的分数,有一个规则,就是连续答对num==k道题那么分数就翻倍,然后num清零,从新开始计数,到大连续k道的时候
 2 要先加上这道题的分数1,再乘以2,
 3 做法:先将n中排出n/k个块,然后分类讨论,当n/k<=(n - m)时,那么说明有n/k个块,因为要连续对k-1道题错一道,所以假设其中错的那道题是一个空格,
 4 如果满足n/k<=(n-m),,即n-m表示答错的题目的个数,说明m个数之间有足够的错误题目来隔开,那么就保证了m道题都在n/k个块中,那么答案就是m,当n/k>n-m那么说明n/k个块之间有些不能隔开,就是会出现连续的答对超过k的情况
 5 所这种情况,采用插空法,每次插一个空分数就会翻倍,当插入一个空,那么分数是2*k,第二个是(2*k+k)*2 =2*k+4k,到第三个的时候总分是2k+4k+8k
 6 以此类推,那么如果剩下的数目是remin,那么就要插remin个空,根据等比数列求和公式;结果是k*2*(2^(remin)-1)表示插入最后一个是所得的分数,那么再加上后面的分数
结果就是k*2*(2^(remin)-1)+m-k*renin
7 #include<stdio.h> 8 #include<string.h> 9 #include<algorithm> 10 using namespace std; 11 const __int64 mod=1000000009; 12 __int64 exp(__int64 a,__int64 n) 13 { 14 __int64 t; 15 if(n==0) return 1%mod; 16 if(n==1) return a%mod; 17 t=exp(a,n/2); 18 t=t*t%mod; 19 if( (n&1)==1) t=t*a%mod; 20 return t; 21 } 22 int main() 23 { 24 __int64 n, m, k,ok, ans; 25 while(scanf("%I64d%I64d%I64d",&n,&m,&k)!=EOF) 26 { 27 if(n < k * (n - m + 1)) 28 printf("%I64d", m); 29 30 else 31 { 32 ok = n / k - n + m; 33 ans = ((k * (exp(2, ok + 1) - 2 )) % mod + m-ok*k+ mod) % mod; 34 printf("%I64d", ans); 35 } 36 } 37 return 0; 38 } 39 40 41 42 43 44 45 46

 

posted on 2013-08-17 16:04  ok_boy  阅读(505)  评论(0编辑  收藏  举报

导航