CF898F.Restoring the Expressio.(哈希)

题目链接:https://vjudge.net/contest/361017#problem/H
http://codeforces.com/problemset/problem/898/F
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
这道题题意并不难理解,就是讲一个字符串分成三段a、b、c,使a+b+c成立
解题思路:
利用哈希的特点,将p设置为10,这样就可以模拟10进制数来进行操作。
我使用了双哈希防止出错。
注意点:
1.特判a、b、c的前导0情况
2.防止超时,找到a、b、c之间的关系。(我一开始是直接i、j进行遍历,结果在第59组数据的地方超时了)
3.在输出a+b=c时,注意不要直接输出,而是要找到原来他们在字符串中的位置,因为a、b、c可能是取模后的值,不一定与原字符串中的相同

在这里插入图片描述

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define ll unsigned long long
#define maxn 1000100
const int mod=1e9+7;
const int mod2=49157;
const int p=10;

ll Hash[maxn];
ll Hash2[maxn];
ll idx[maxn];
ll Pow[maxn];
ll Pow2[maxn];
string s;
int len;
ll a,b,c;
ll a2,b2,c2;
int la,ra,lb,rb,lc,rc;
void get_hash()
{
	Pow[0]=1;
	Pow2[0]=1;
	for(int i=1;i<=maxn/2;i++)
	{
	Pow[i]=Pow[i-1]*p%mod;
	Pow2[i]=Pow2[i-1]*p%mod2;
	}

	idx[0]=s[0]-'0';
	Hash[0]=idx[0];
	Hash2[0]=idx[0];
	for(int i=1;i<len;i++)
	{
		idx[i]=s[i]-'0';
		Hash[i]=(Hash[i-1]*p+idx[i])%mod;
		Hash2[i]=(Hash2[i-1]*p+idx[i])%mod2;
	}
}

ll cmp_hash(int l,int r)
{
	if(l==0)
		return Hash[r];
	return (Hash[r]+mod-(Hash[l-1]*Pow[r-l+1])%mod)%mod;
}
ll cmp_hash2(int l,int r)
{
	if(l==0)
		return Hash2[r];
	return (Hash2[r]+mod2-(Hash2[l-1]*Pow2[r-l+1])%mod2)%mod2;
}
int main()
{
	
	int flag=0;
	cin>>s;
	len=s.size();
	get_hash();
	int i,j;
	for(i=1;i<=len/2;i++)
	{
		if(i>1&&idx[0]==0)
			break;
		a=cmp_hash(0,i-1);
		a2=cmp_hash2(0,i-1);
		if(i<len/3+1)
		{
			j=(len-i)/2;
			if(!(idx[i]==0&&j>1)&&!(len-i-j>1&&idx[i+j]==0)){
			b=cmp_hash(i,i+j-1);   b2=cmp_hash2(i,i+j-1);
			c=cmp_hash(i+j,len-1); c2=cmp_hash2(i+j,len-1);
			if((a+b)%mod==c%mod&&(a2+b2)%mod2==c2%mod2)
			{
				flag=1;
				la=0;ra=i-1;
				lb=i;rb=i+j-1;
				lc=i+j;rc=len-1;
				break;
			}
			}
			j=(len-i-1)/2;
			if(!(idx[i]==0&&j>1)&&!(len-i-j>1&&idx[i+j]==0)){
			b=cmp_hash(i,i+j-1);   b2=cmp_hash2(i,i+j-1);
			c=cmp_hash(i+j,len-1); c2=cmp_hash2(i+j,len-1);
			if((a+b)%mod==c%mod&&(a2+b2)%mod2==c2%mod2)
			{
				flag=1;
				la=0;ra=i-1;
				lb=i;rb=i+j-1;
				lc=i+j;rc=len-1;
				break;
			}
			}
		}
		if(i>(len-1)/3-1)
		{
			j=len-2*i;
			if(!(idx[i]==0&&j>1)&&!(len-i-j>1&&idx[i+j]==0)){
			b=cmp_hash(i,i+j-1);   b2=cmp_hash2(i,i+j-1);
			c=cmp_hash(i+j,len-1); c2=cmp_hash2(i+j,len-1);
			if((a+b)%mod==c%mod&&(a2+b2)%mod2==c2%mod2)
			{
				flag=1;
				la=0;ra=i-1;
				lb=i;rb=i+j-1;
				lc=i+j;rc=len-1;
				break;
			}
			}
			j=len-2*i-1;
			if(!(idx[i]==0&&j>1)&&!(len-i-j>1&&idx[i+j]==0)){
			b=cmp_hash(i,i+j-1);   b2=cmp_hash2(i,i+j-1);
			c=cmp_hash(i+j,len-1); c2=cmp_hash2(i+j,len-1);
			if((a+b)%mod==c%mod&&(a2+b2)%mod2==c2%mod2)
			{
				flag=1;
				la=0;ra=i-1;
				lb=i;rb=i+j-1;
				lc=i+j;rc=len-1;
				break;
			}
			}
		}
		if(flag==1)
			break;
	}
	if(flag==1)
	{
		//注意这里不可以直接输出a+b=c
		//a b c可能是取模后的值
		for(int i=la;i<=ra;i++)
			printf("%d",idx[i]);
		cout<<"+";
		for(int i=lb;i<=rb;i++)
			printf("%d",idx[i]);
		cout<<"=";
		for(int i=lc;i<=rc;i++)
			printf("%d",idx[i]);
		cout<<endl;
	}
	return 0;
}


	
	

原创文章 65 获赞 3 访问量 2115

猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/104813202