字符串哈希--聪聪的加法等式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sizeof_you/article/details/83789367

题目:
聪聪昨天费了九牛二虎之力终于计算出一个形如 A + B = C A+B=C 加法算式。
但是调皮的明明,却将他计算的式子中的加号和等号用橡皮擦去,于是式子只剩下形如 A B C ABC 的数字串了。
然而气急败坏的聪聪却怎么也还原不出原来的等式了,这可怎么办呀?你能帮帮他吗?

长度 1 0 6 \le 10^6

solution:
因为和只能和大加数位数一样活着多一位,所以枚举 A A ,然后哈希判断是否合法

顺便说单哈希绝对被卡了,数据居然还卡双哈希真是惊了,据说题解是随机哈希,然而双哈希只要设不那么常用的模数就可以过了,比如 1 e 9 + 19 1e9+19 998244853 998244853 ,我试了一下 1 e 9 + 7 , 1 e 9 + 9 , 998244353 1e9+7,1e9+9,998244353 都被卡了,不得不说数据实在太强了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 1000005
#define int long long
using namespace std;
int n,has1[maxn],has2[maxn],ans,ans2,pw1[maxn],pw2[maxn];
const int bas=10,mod1=1e9+19,mod2=998244853;
char s[maxn];

inline void solve(int len,int i){
	int b,res;
	b=(has1[n-len]-has1[i]*pw1[n-len-i]%mod1+mod1)%mod1;
	res=(has1[n]-has1[n-len]*pw1[len]%mod1)%mod1;
	res=(res+mod1)%mod1; 
	if((has1[i]+b)%mod1!=res) return;
	b=(has2[n-len]-has2[i]*pw2[n-len-i]%mod2+mod2)%mod2;
	res=(has2[n]-has2[n-len]*pw2[len]%mod2)%mod2;
	res=(res+mod2)%mod2;
	if((has2[i]+b)%mod2==res) ans=i; return;
}

signed main(){
	scanf("%s",s+1); n=strlen(s+1); pw1[0]=pw2[0]=1;
	for(int i=1;i<=n;i++){
		pw1[i]=pw1[i-1]*bas%mod1;
		pw2[i]=pw2[i-1]*bas%mod2;
		has1[i]=(has1[i-1]*bas%mod1+s[i]-'0')%mod1;
		has2[i]=(has2[i-1]*bas%mod2+s[i]-'0')%mod2;
	}
	int len,b,res;
	for(int i=1;i<=n/2;i++){//枚举A 
		len=(n-i+1)>>1;
		if(len<i) len=i;
		if(s[i+1]=='0' && len+i!=n-1) continue;
		solve(len,i);
		if(ans) {ans2=n-len;break;}
		if(len+1+i<n){
			++len; solve(len,i);
			if(ans) {ans2=n-len;break;}
		}
	}
	for(int i=1;i<=ans;i++) printf("%c",s[i]);
	printf("+");
	for(int i=ans+1;i<=ans2;i++) printf("%c",s[i]);
	printf("=");
	for(int i=ans2+1;i<=n;i++) printf("%c",s[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sizeof_you/article/details/83789367