ABC164 D.Multiple of 2019

D.Multiple of 2019

Question

给一个字符串S,求有多少个子串在十进制下为2019的倍数。
在这里插入图片描述

Solution

前置知识:
S [ l ] [ r ] × 1 0 l r = s [ l ] [ k ] s [ r ] [ k ] S[l][r]\times10^{l-r}=s[l][k]-s[r][k]
S [ l ] [ k ] S [ r ] [ k ] 0 ( m o d   P ) S[l][k]-S[r][k] \equiv 0(mod\ P)
1 0 x m o d   P 0 ∵10^{x} mod\ P \neq 0
S [ l ] [ r ]   m o d   P = 0 ∴S[l][r]\ mod \ P =0
S [ l ] [ r ] 0 ( m o d   P ) S[l][r] \equiv 0(mod\ P)
S [ l ] [ r ] × 1 0 r l   m o d   P = 0 S[l][r] \times 10^{r-l} \ mod \ P = 0

这道题再增加难度就是任意模数 P P 了二不一定是 2019 2019 ,上面证明了任意模数P非10的因子的情况下。
下面讲如何处理 P P 10 10 的因子情况下 : :
1 1 n n 遍历若一个数个位为 10 10 的因子,则前面的数肯定是 10 10 的倍数,所以前面的数被 P P 取余一定为 0 0
对应的ABC158E

将题意转化为对2019求余为0的子串有多少个。求一个后缀模数数组,后缀数组取模后的数为 i i ,后缀数组取模后为 i i 的个数为 M [ i ] M[i]
i = M [ i ] ( M [ i ] 1 ) / 2 i的贡献值=M[i]*(M[i]-1)/2 这里可以转化为加法,加上之前已有的 M [ i ] M[i] 之后再更新 M [ i ] M[i] ,注意初始化 M [ 0 ] = 1 M[0]=1

Code ABC164D

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF  = 0x3f3f3f3f;
const ll  mod  = 2019;
const ll  maxn = 1e6 + 5;
const int N = 2e5 + 5;

char s[N];
int a[N],suf[N],n,M[2020];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>s+1;
	int n=strlen(s+1);
	int cnt=0;int base=1;
	M[0]++;
	for(int i=n;i>=1;i--){
		a[i]=s[i]-'0';
		suf[i]=(suf[i+1]+a[i]*base)%mod;
		cnt+=M[suf[i]];
		M[suf[i]]++;
		base=base*10%mod;
	}
	cout<<cnt<<'\n';
	return 0;
}

Code2 ABC158E

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF  = 0x3f3f3f3f;
const ll  mod  = 1e9 + 7;
const ll  maxn = 1e6 + 5;
const int N = 2e5 + 5;

char s[N];
int suf[N],cnt[N];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,p;cin>>n>>p>>s+1;
	int base=1;
	ll ans=0;
	if(10%p==0){
		for(int i=1;i<=n;i++){
			if((s[i]-'0')%p==0) ans+=i;
		}
	}else{
		cnt[0]++;
		for(int i=n;i>=1;i--){
			int j=s[i]-'0';
			suf[i]=(suf[i+1]+j*base)%p;
			ans+=cnt[suf[i]];
			cnt[suf[i]]++;
			base=base*10%p;
		}
	}
	cout<<ans<<'\n';
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Meulsama/article/details/105791694