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

本文介绍了一种使用双哈希算法解决特定数学问题的方法。通过枚举和双哈希判断,解决了由聪聪提出的加法算式还原问题。文章详细解释了算法原理,包括如何设置模数避免数据冲突,并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

长度 ≤ 1 0 6 \le 10^6 106

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

顺便说单哈希绝对被卡了,数据居然还卡双哈希真是惊了,据说题解是随机哈希,然而双哈希只要设不那么常用的模数就可以过了,比如 1 e 9 + 19 1e9+19 1e9+19 998244853 998244853 998244853,我试了一下 1 e 9 + 7 , 1 e 9 + 9 , 998244353 1e9+7,1e9+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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值