给定一个长度为 n 的纯大写字母字符串,我们想要知道,这个字符串有多少个连续子串,内部有至少 k 个 R,且不包含 P。
1≤n≤2∗105,1≤k≤20
官方题解有两个解法,我们这里用第二个(因为我也是用第二个方法过的)。
我们枚举左端点 L,发现右端点 R 必须满足:
区间 [L,R] 内 R 的数量要大于等于 k
区间 [L,R] 内没有P,也就是说 P 的数量要小于等于 1
这两个都具有单调性质,所以可以分别求出来对应的边界,R 只要夹在他俩中间即可。
这个方法不太好写双指针,只能二分,不过改一下的话就可以了:我们将字符串沿着 P 分开,分成若干个子串,这样在这些子串内部求区间(此时要求只剩下了 R 的数量大于等于 k 这一限制),这样就可以愉快的双指针了。
//二分代码#include<bits/stdc++.h>usingnamespace std;
constint N = 200010;
int n, k, a[N], b[N];
char s[N];
intmain(){
//readscanf("%d%d%s", &n, &k, s + 1);
//solvefor (int i = 1; i <= n; ++i)
if (s[i] == 'R') a[i] = 1;
elseif (s[i] == 'P') b[i] = 1;
for (int i = 1; i <= n; ++i)
a[i] += a[i - 1], b[i] += b[i - 1];
longlong ans = 0;
for (int i = 1; i <= n; ++i) {
if (a[n] - a[i - 1] < k || s[i] == 'P') continue;
int L = lower_bound(a + 1, a + n + 1, a[i - 1] + k) - a;
int R = upper_bound(b + 1, b + n + 1, b[i - 1]) - b - 1;
ans += max(0, R - L + 1);
}
printf("%lld", ans);
return0;
}
例如第 i 个值为 x,那么我们选定这个值作为最小值,那么在它前面的都不选,后面的都可以选,那么 x 作为最小值就出现了 2n−i 次;同理,其作为最大值出现了 2i−1 次。
我们综合一下,发现答案为
ans=(n∏i=1a2n−ii)(n∏i=1a2i−1i)
质数过大,加上不保证互质性质,所以则套一个扩展欧拉降幂。
注:若 x 是质数,则 ϕ(x)=x−1,所以本题不需要单独写欧拉函数了。
#include<bits/stdc++.h>usingnamespace std;
#define LL long longconstint N = 200010;
const LL mod = 1e9 + 7, P = 1e9 + 6;
int n;
LL a[N];
LL power(LL a, LL b, LL M){
LL res = 1;
while (b) {
if (b & 1) res = res * a % M;
b >>= 1;
a = a * a % M;
}
return res;
}
LL solve(LL x, LL y){
LL p = power(2, y, P);
if (y < 30) returnpower(x, p, mod);
elsereturnpower(x, p + P, mod);
}
intmain(){
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
sort(a + 1, a + n + 1);
LL ans = 1;
for (int i = 1; i <= n; ++i)
ans = ans * solve(a[i], n - i) % mod;
for (int i = 1; i <= n; ++i)
ans = ans * solve(a[i], i - 1) % mod;
cout << ans << endl;
return0;
}
#include<bits/stdc++.h>usingnamespace std;
constint N = 30010;
#define LL long longconst LL mod = 1e9 + 7;
//boolcheck(int x){
for (int i = 2; i * i <= x; ++i)
if (x % i == 0) returntrue;
returnfalse;
}
int cnt[N];
int p[N], c[N];
voiddivide(int x){
//divideint m = 0;
for (int i = 2; i <= sqrt(x); ++i)
if (x % i == 0) {
p[++m] = i, c[m] = 0;
while (x % i == 0) x /= i, c[m]++;
}
if (x > 1) p[++m] = x, c[m] = 1;
//updatefor (int i = 1; i <= m; ++i)
cnt[p[i]] = max(cnt[p[i]], c[i]);
}
LL power(LL a, LL b){
LL res = 1;
while (b) {
if (b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
intmain(){
int l, r;
cin >> l >> r;
bool flag = false;
for (int i = l; i <= r; ++i)
if (check(i)) {
flag = true;
divide(i);
}
if (!flag) {
puts("-1");
return0;
}
LL ans = 1;
for (int i = 1; i < N; ++i)
ans = ans * power(i, cnt[i]) % mod;
cout << ans;
return0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2021-02-16 CF教育场 104 解题补题报告