C. Good Subarrays+K倍区间(对前缀和思想的妙用)

参考大佬的思路发现能更清晰解决蓝桥杯的问题:女少口阿


链接:C. Good Subarrays
题意:给出一个0~9的字符串,求出任意字串和与字串长度相等的字串数目。
思路:

  • 若字符为1自身就满足一个字串
  • 若为2—9,任意值其后就要跟1—8个0才能满足这个字串和和长度相等
  • 所以这里把0看作-1,把1看作0,把2—9看作1—8
  • 记录每个前缀和出现的次数

思想:若1–i前缀和为3, 1— i + k 1 i+k_1 i+k1的前缀和也为3,1— i + k 2 i+k_2 i+k2的前缀和也是3……
那么i+1— i + k 1 i+k_1 i+k1,i+1— i + k 2 i+k_2 i+k2的前缀和就为0

/*
	事实上并没有记录前缀和数组
	我们用map数组记录了每个前缀和出现的次数 
*/
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+5;
int T, n;
char a[N];
map<int,int> mp;
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		mp.clear();
		scanf("%d",&n);
		scanf("%s",a+1);
		int x=0;
		for(int i=1;i<=n;i++){
			x+=a[i]-'0'-1;
			mp[x]++;
		}
		long long ans=mp[0];  //前缀和为0的本身即为答案 
		x=0;
		for(int i=1;i<=n;i++){
			x+=a[i]-'0'-1;  
			mp[x]--;
			ans+=mp[x];   //加上去掉1~i后符合要求了的子串数目
		} 
		printf("%lld\n",ans);		
	}
	return 0;
}

K倍区间问题:https://www.acwing.com/problem/content/1232/

以同样的思路解决

#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
const int N=1e5+5;
typedef long long LL;
int a[N];
map<int,int> mp;

int main(){
	int n,k;
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	LL x=0;
	for(int i=1;i<=n;i++){
		x+=a[i];
		mp[x%k]++;
	}
	int ans=mp[0];
	x=0;
	for(int i=1;i<=n;i++){
		x+=a[i];
		mp[x%k]--;
		ans+=mp[x%k];
	} 
	printf("%lld\n",ans);
	return 0;
}

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页