The Sum of Good Number

题解

这种高精加法哈希比较的题真的很臭呀,赛后一群人在那里卡模数,真的吐了

我们考虑如何快速比较两个大整数的和,显然,哈希是一种很好的方法,所以我们可以将比较两个很长的大整数的和转换成比较它们哈希值的和。
由于我们所有的数都是 “好数” ,也就是不含 000 的数,所以它的进位一定是比较少的,其进位最多只会比做加法的两个数多出 111 位。
所以我们加的两个数要么是长度几乎相当,都是 ∣x∣|x|∣x∣ 或 ∣x∣−1|x|-1∣x∣−1,要么较长的为 ∣x∣|x|∣x∣,其前缀的大部分都与我们目标的xxx相同。

对于前面的都是 ∣x∣|x|∣x∣ 或 ∣x∣−1|x|-1∣x∣−1 的情况,我们可以特殊记录一下,从每个点开始的长度为∣x∣|x|∣x∣或者 ∣x∣−1|x|-1∣x∣−1 的前缀的哈希值,将相邻的两个加起来,判断它的哈希值是否等于我们目标xxx的哈希值。
对于第二种情况,我们可以猜测大部分情况下与前缀大部分与我们目标xxx相同的数是比较少,对于每个这样的前缀就暴力枚举其往前扩散与往后扩散的哈希值,看是否存在一个使得加起来可以达到我们目标的xxx。

由于赛后一群人在那里卡哈希,把笔者都给卡*了,所以笔者用的是随机的哈希数,也就是先列出一大堆哈希数,每次从里面随机出两个作为这次的哈希模数。

也许常数会有点大。
时间复杂度 O(∣s∣+∣x∣)O\left(|s|+|x|\right)O(∣s∣+∣x∣)。

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 500005
#define MAXM (1<<20)+5
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int inv2=499122177;
const int jzm=2333;
const int n1=50;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){putchar('\n');while(x>9){putchar((x%10)|'0');x/=10;}putchar(x|'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int lens,lenx,mod1,mod2;pii nowx,sum1[MAXN],sum2[MAXN];
int mp[15]={100001651,100001623,100001611,100001591,100001581,100001569,100001537,100001533,100001507,100001467};
char str[MAXN],x[MAXN];
pii operator + (pii x,pii y){return mkpr(add(x.fir,y.fir,mod1),add(x.sec,y.sec,mod2));}
bool operator == (pii x,pii y){return x.fir==y.fir&&x.sec==y.sec;}
signed main(){scanf("%s\n%s",str+1,x+1);mt19937 e(time(0));uniform_int_distribution<int> g(0,9);int u=g(e),v=g(e);mod1=mp[u];mod2=mp[v];lens=(int)strlen(str+1);lenx=(int)strlen(x+1);pii num1=mkpr(1,1),num2=mkpr(1,1);for(int i=1;i<=lenx;i++)nowx.fir=(10ll*nowx.fir+(x[i]-'0'))%mod1,nowx.sec=(10ll*nowx.sec+(x[i]-'0'))%mod2;for(int i=1;i<=lenx;i++)num1.fir=10ll*num1.fir%mod1,num1.sec=10ll*num1.sec%mod2;for(int i=1;i<lenx;i++)num2.fir=10ll*num2.fir%mod1,num2.sec=10ll*num2.sec%mod2;for(int i=1;i<=lenx;i++)sum1[lenx].fir=(10ll*sum1[lenx].fir+1ll*(str[i]-'0'))%mod1,sum1[lenx].sec=(10ll*sum1[lenx].sec+1ll*(str[i]-'0'))%mod2;for(int i=1;i<lenx;i++)sum2[lenx-1].fir=(10ll*sum2[lenx-1].fir+1ll*(str[i]-'0'))%mod1,sum2[lenx-1].sec=(10ll*sum2[lenx-1].sec+1ll*(str[i]-'0'))%mod2;for(int i=lenx+1;i<=lens;i++)sum1[i].fir=(10ll*sum1[i-1].fir+1ll*(str[i]-'0')-1ll*num1.fir*(str[i-lenx]-'0')%mod1+1ll*mod1)%mod1,sum1[i].sec=(10ll*sum1[i-1].sec+1ll*(str[i]-'0')-1ll*num1.sec*(str[i-lenx]-'0')%mod2+1ll*mod2)%mod2;for(int i=lenx;i<=lens;i++)sum2[i].fir=(10ll*sum2[i-1].fir+1ll*(str[i]-'0')-1ll*num2.fir*(str[i-lenx+1]-'0')%mod1+1ll*mod1)%mod1,sum2[i].sec=(10ll*sum2[i-1].sec+1ll*(str[i]-'0')-1ll*num2.sec*(str[i-lenx+1]-'0')%mod2+1ll*mod2)%mod2;for(int i=lenx+lenx-2;i<=lens;i++){if(i>=lenx+lenx&&sum1[i]+sum1[i-lenx]==nowx){printf("%d %d\n%d %d\n",i-lenx-lenx+1,i-lenx,i-lenx+1,i);return 0;}if(lenx>1&&i>=lenx+lenx-1&&sum1[i]+sum2[i-lenx]==nowx){printf("%d %d\n%d %d\n",i-lenx-lenx+2,i-lenx,i-lenx+1,i);return 0;}if(lenx>1&&i>=lenx+lenx-1&&sum2[i]+sum1[i-lenx+1]==nowx){printf("%d %d\n%d %d\n",i-lenx-lenx+2,i-lenx+1,i-lenx+2,i);return 0;}if(lenx>1&&sum2[i]+sum2[i-lenx+1]==nowx){printf("%d %d\n%d %d\n",i-lenx-lenx+3,i-lenx+1,i-lenx+2,i);return 0;}}for(int i=lenx+1;i<=lens;i++){bool flag=0;for(int j=1;j<=min(10,lenx);j++)if(str[i-lenx+j]^x[j])flag=1;if(flag&&lenx>10)continue;pii summ=mkpr(0,0),num=mkpr(1,1);for(int j=1;j<=min(lenx,i-lenx);j++){summ.fir=(1ll*summ.fir+1ll*num.fir*(str[i-lenx-j+1]-'0'))%mod1;summ.sec=(1ll*summ.sec+1ll*num.sec*(str[i-lenx-j+1]-'0'))%mod2;if(sum1[i]+summ==nowx){printf("%d %d\n%d %d\n",i-lenx-j+1,i-lenx,i-lenx+1,i);return 0;}num.fir=10ll*num.fir%mod1;num.sec=10ll*num.sec%mod2;}summ=mkpr(0,0);for(int j=1;j<=min(lenx,lens-i);j++){summ.fir=(10ll*summ.fir+str[i+j]-'0')%mod1;summ.sec=(10ll*summ.sec+str[i+j]-'0')%mod2;if(sum1[i]+summ==nowx){printf("%d %d\n%d %d\n",i-lenx+1,i,i+1,i+j);return 0;}}num=mkpr(1,1);summ=mkpr(0,0);for(int j=1;j<=min(lenx-1,i-lenx+1);j++){summ.fir=(1ll*summ.fir+1ll*num.fir*(str[i-lenx-j+2]-'0'))%mod1;summ.sec=(1ll*summ.sec+1ll*num.sec*(str[i-lenx-j+2]-'0'))%mod2;if(sum2[i]+summ==nowx){printf("%d %d\n%d %d\n",i-lenx-j+2,i-lenx+1,i-lenx+2,i);return 0;}num.fir=10ll*num.fir%mod1;num.sec=10ll*num.sec%mod2;}summ=mkpr(0,0);for(int j=1;j<=min(lenx-1,lens-i);j++){summ.fir=(10ll*summ.fir+str[i+j]-'0')%mod1;summ.sec=(10ll*summ.sec+str[i+j]-'0')%mod2;if(sum2[i]+summ==nowx){printf("%d %d\n%d %d\n",i-lenx+2,i,i+1,i+j);return 0;}}}return 0;
}

谢谢!!!

[CF1598G]The Sum of Good Numbers相关推荐

  1. lintcode: Check Sum of Square Numbers

    Check Sum of Square Numbers Given a integer c, your task is to decide whether there're two integers ...

  2. LeetCode633 | Sum of Square Numbers (Easy)

    题目地址(633. 平方数之和) https://leetcode-cn.com/problems/sum-of-square-numbers/ 题目描述 给定一个非负整数 c ,你要判断是否存在两个 ...

  3. C#LeetCode刷题之#633-平方数之和( Sum of Square Numbers)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3885 访问. 给定一个非负整数 c ,你要判断是否存在两个整数 ...

  4. LeetCode 985 Sum of Even Numbers After Queries 解题报告

    题目要求 We have an array A of integers, and an array queries of queries. For the i-th query val = queri ...

  5. 633. Sum of Square Numbers

    题目就是非负正数 c,是否可以写成c**2 = a**2+b**2 1.缩写范围,因为是平方和,所以a,b两个数一个在c的平方根内 2.循环得出另一个数的平方 3.这里用到一个小技巧,一个数的平方开方 ...

  6. Sum of Even Numbers After Queries

    Solution: 转载于:https://www.cnblogs.com/Julietma/p/10414394.html

  7. LeetCode 633. Sum of Square Numbers

    Given a non-negative integer c, your task is to decide whether there're two integers a and b such th ...

  8. 633.平方数之和(Sum of Square Numbers)

    题目描述 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c. 示例1: 输入: 5 输出: True 解释: 1 * 1 + 2 * 2 = 5 示例2: 输 ...

  9. [leetcode] Minimum Path Sum

    Minimum Path Sum Given a m x n grid filled with non-negative numbers, find a path from top left to b ...

最新文章

  1. 微信小程序点击右下角的图片移动到当前位置
  2. VirtualBox安装64位Linux
  3. 云计算的7种变化方式
  4. mongodb启动不了:child process failed, exited with err
  5. SpringMVC如何获取请求带来的各种信息 ||如果我们的请求参数是一个POJO(自定义参数类型), SpringMVC会自动的为这个POJO进行赋值
  6. 操作系之进程调度及算法详解
  7. 使用Spring提供Quartz来实现定时任务
  8. 网易云音乐上线Beat交易平台 收益100%归制作人所有
  9. JavaSE11: 简单快速掌握枚举
  10. CSS animation 与 transition 有何区别?
  11. Vue:vue将按需引入element抽成单独js文件
  12. 深入浅出通信原理连载145-389(Python代码版)
  13. local.china java_java-JDBC无法登录到LocalDB实例,但是在SSMS中,...
  14. inputstream 占用内存吗_明明是8G的内存,系统却显示只有4G!为什么电脑这么吃内存?...
  15. xshell堡垒机_XShell运维工具之跳板机配置
  16. 双系统装完只能u盘启动_怎样用u盘安装双系统呢?
  17. OVER(PARTITION BY)使用方法
  18. Java入门 二维数组、一维数组、多维数组的解析(第十三天)
  19. 【BUG记录】Idea spring boot项目中target中没有同步更新最新目录文件及资源
  20. MobaXterm 详细安装使用教程 官网

热门文章

  1. windows 程序设计 剪切板
  2. 大数据应用市场前景如何?
  3. [ORACLE]java.sql.SQLRecoverableException: IO Error: Connection rese
  4. 大厂面试系列(中)—拿到蚂蚁金服社招offer,过来还愿分享面经
  5. 易优cms忘记后台登陆密码?解决方法 Eyoucms快速入门
  6. Origin图例排布修改与图例边框去除
  7. sql-labs 闯关 21~25
  8. 基于ElementUI的一个文件批量上传,下载,删除以及图片预览组件(样式篇)
  9. 趣谈网络原理 多交换机和VLAN(自我提升第十七天)
  10. 福昕阅读器多窗口/标签 打开同一个pdf文件