标签:
题目链接:点击打开链接
题意:有一个等差数列,从A开始,公差为B
然后n个询问。。。每个询问给定l,t,m
然后要求如果每次可以最多选择m个数,使这m个数-1,那么在t次操作中可以使l为左端点的最长序列中使所有数为0
思路:
枚举答案判可行就好了。
有一个结论,就是只要最大的数<=t,那么一定存在某种方案使得:当和 <= t*m 时能把所有数消光。
#include <stdio.h> #include <string.h> #include <string> #include <math.h> #include <map> #include <vector> #include <set> #include <algorithm> #include <iostream> using namespace std; template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if (x>9) pt(x / 10); putchar(x % 10 + '0'); } typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int N = 1e6 + 10; const int mod = 1e9 + 7; int n; ll A, B; ll l, t, m, mx; ll siz(ll x){ return A + (x - 1)*B; } ll work(){ if (siz(l) - t > 0)return -1; ll L = l, R = mx, ans = l; while (L <= R){ ll mid = (L + R) >> 1; ll len = mid - l + 1; ll all = (siz(l) + siz(mid))*len / 2; ll M = min(m, len); if (all > t*M || siz(mid)>t) R = mid - 1; else { ans = mid; L = mid + 1; } } return ans; } int main() { while (cin >> A >> B >> n){ mx = (1e6 - A) / B; mx++; while (n--){ rd(l); rd(t); rd(m); pt(work()); puts(""); } } return 0; }
Codeforces 536A Tavas and Karafs 二分+结论
标签:
原文地址:http://blog.csdn.net/qq574857122/article/details/45058617