题意:
有n到题,按顺序做,做完一道,得分+1。同时计数器显示连续作对的题数,如果题数大于k,此时的成绩扩大一倍。求作对m道题得到的最少分数。
思路:
贪心的算,从末尾每k-1个位置放一个没有做对的题,这样倍数最小。
对于前面的每k个翻一倍,可以得到这个公式:……2(2(2k + k)+k)……。整理就是:k*(2^pre + 2^(pre-1)……+2),对于后面,没有翻倍,直接加上就可以,注意前面还可能有没有翻倍的余项。
还有就是 是对1e9+9取余,不是1e9+7 。。。。。。。。。。。。。
#include <map> #include <set> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <iostream> #include <stack> #include <cmath> #include <string> #include <vector> #include <cstdlib> //#include <bits/stdc++.h> //#define LOACL #define space " " using namespace std; //typedef long long LL; typedef __int64 Int; typedef pair<int, int> paii; const int INF = 0x3f3f3f3f; const double ESP = 1e-5; const double PI = acos(-1.0); const long long MOD = 1000000009; const int MAXN = 100000 + 10; Int pow_mod(Int y) { Int rec = 1; Int base = 2LL; while (y) { if (y&1) rec = base%MOD*rec%MOD; base = base%MOD*base%MOD; y >>= 1; } return rec; } int main() { Int n, m, k; while (scanf("%I64d%I64d%I64d", &n, &m, &k) != EOF) { Int ans = 0, res; if (n < k*(n - m + 1)) {printf("%I64d ", m);} else { m = n - m; Int pre = (n - k*m)/k; res = (n - m*k)%k; //须要加上一个MOD在进行取余,防止取余取到一个特小的数 44组测试数据卡这里 ans = (k%MOD*(pow_mod(pre + 1) - 2)%MOD + res + m*(k - 1)%MOD + MOD)%MOD; printf("%I64d ", ans); } } return 0; }