CF1996E Decode

这题我竟然做出来了/jy

题目要求所有子区间的子区间的贡献之和,那么一个子区间 [l,r] 的贡献就要乘上 l(nr+1),因为左端点在 [1,l] 内,右端点在 [r,n] 范围内的区间均包含该区间。

我们令 01,计算前缀和 s,那么一个区间 [l,r]0 的个数等于 1 个个数等价于 sr=sl1。我们考虑枚举右端点 r,去数 [0,r1] 内有多少个 si 满足 si=sr。所有的区间要乘上系数 (i+1)(nr+1),故贡献之和为 (nr+1) 乘上所有满足的 i+1 之和。这里我们可以用数组 cnti 表示 [0,i1] 内满足 sj=sij+1 之和,实现的时候注意负数的情况。时间复杂度为 O(n)

代码:

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mk make_pair
#define ll long long
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;

typedef vector <int> vi;
typedef pair <int, int> pii;

inline int rd() { int x = 0, f = 1; char c = getchar(); while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); while (isdigit(c)) x = (x<<3)+(x<<1)+(c^48), c = getchar(); return x*f; }
template <typename T> inline void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x/10); putchar(x%10+48); }

const int mod = 1e9+7;
char c[200005];

void solve() {
	cin >> (c+1);
	int n = strlen(c+1), ans = 0; vi s(n+1), cnt(n*2+5);
	for (int i = 1; i <= n; ++i) {
		s[i] = c[i] == '0' ? -1 : 1;
		s[i] += s[i-1];
	}
	cnt[n] = 1;
	for (int i = 1; i <= n; ++i) {
		ans = (ans+1ll*(n-i+1)*cnt[s[i]+n]%mod)%mod;
		cnt[s[i]+n] = (cnt[s[i]+n]+i+1)%mod;
	}
	cout << ans << '\n';
}

int main() {
	int t = rd();
	while (t--) solve();
	return 0;
}
posted @   123wwm  阅读(11)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示