Problem A:
实际上对于一段数字假设和为k,每次取较大的m个进行t次减一操作,最多减去的是min(m*t,k).
明白了这个结论就可以直接二分答案了。
#include <bits/stdc++.h> #define LL long long using namespace std; LL A, B, n; LL l, t, m, ans; int main() { ios::sync_with_stdio (0); cin >> A >> B >> n; for (int i = 1; i <= n; i++) { cin >> l >> t >> m; LL a = A + (l - 1) * B; int el = l, er = l + t, last = -1; while (el <= er) { int mid = (el + er) >> 1; LL b = A + (mid - 1) * B; if ( (a + b) * (mid - l + 1) / 2 <= t * m && b <= t && t >= a) last = mid, el = mid + 1; else er = mid - 1; } cout << last << endl; } }
Problem B:
对于匹配串p,的位置xi和xj 只要判断是否有冲突,没有的冲突的话,统计确定的位置的数量k,答案就是26^(n-k).否则答案就是0.
判断冲突利用KMP的next数组就行了.
#include <bits/stdc++.h> #define LL long long using namespace std; const int MAXN = 1000009; const int MOD = int (1e9 + 7); int n, m; int p[MAXN]; char s[MAXN]; int main() { ios::sync_with_stdio (0); cin >> n >> m >> (s + 1); int len = strlen (s + 1); for (int i = 2, j = 0; i <= len; i++) { if (j && s[j + 1] != s[i]) j = p[j]; if (s[j + 1] == s[i]) j++; p[i] = j; } int k = 0; for (int i = 1, x, y = 0; i <= m; i++) { cin >> x; if (y && y + len > x) { int tem = len; while (p[tem] > y + len - x) tem = p[tem]; if (p[tem] != y + len - x) { cout << 0 << endl; return 0; } else k -= y - x; } else if (y && y + len <= x) k += len; y = x; } if(m) k += len; LL ans = 1, tem = 26; k = n - k; while (k) { if (k & 1) ans = (ans * tem) % MOD; tem = (tem * tem) % MOD; k >>= 1; } cout << ans << endl; }