【数论 扩展欧几里得 中国剩余定理】P12364 [蓝桥杯 2022 省 Python B] 寻找整数|普及+

【数论 扩展欧几里得 中国剩余定理】P12364 [蓝桥杯 2022 省 Python B] 寻找整数|普及+

本文涉及知识点

数论:质数、最大公约数、菲蜀定理

P12364 [蓝桥杯 2022 省 Python B] 寻找整数

题目描述

有一个不超过 10 17 10^{17} 1017 的正整数 n n n,知道这个数除以 2 2 2 至 49 49 49 后的余数如下表所示,求这个正整数最小是多少。

a a a n m o d a n \bmod a nmoda a a a n m o d a n \bmod a nmoda a a a n m o d a n \bmod a nmoda a a a n m o d a n \bmod a nmoda
2 2 2 1 1 1 14 14 14 11 11 11 26 26 26 23 23 23 38 38 38 37 37 37
3 3 3 2 2 2 15 15 15 14 14 14 27 27 27 20 20 20 39 39 39 23 23 23
4 4 4 1 1 1 16 16 16 9 9 9 28 28 28 25 25 25 40 40 40 9 9 9
5 5 5 4 4 4 17 17 17 0 0 0 29 29 29 16 16 16 41 41 41 1 1 1
6 6 6 5 5 5 18 18 18 11 11 11 30 30 30 29 29 29 42 42 42 11 11 11
7 7 7 4 4 4 19 19 19 18 18 18 31 31 31 27 27 27 43 43 43 11 11 11
8 8 8 1 1 1 20 20 20 9 9 9 32 32 32 25 25 25 44 44 44 33 33 33
9 9 9 2 2 2 21 21 21 11 11 11 33 33 33 11 11 11 45 45 45 29 29 29
10 10 10 9 9 9 22 22 22 11 11 11 34 34 34 17 17 17 46 46 46 15 15 15
11 11 11 0 0 0 23 23 23 15 15 15 35 35 35 4 4 4 47 47 47 5 5 5
12 12 12 5 5 5 24 24 24 17 17 17 36 36 36 29 29 29 48 48 48 41 41 41
13 13 13 10 10 10 25 25 25 9 9 9 37 37 37 22 22 22 49 49 49 46 46 46

输入格式

输出格式

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只需要编写一个程序输出这个整数,输出多余的内容将无法得分。

数论 扩展欧几里得 中国剩余定理

令本题答案是X, 令a[i] = 2 + i, b[i] = x % a[i],b[i] 可以查本题的表得到。
将48个{a[i],b[i]}放到栈中。
如果栈中只有一个元素,则b就是答案。
如果栈中有2个及更多元素。分别为{a1, b1},{ a2,b2},出栈这两个元素。
枚举 y = ( b 1 + a 1 ∗ i ) y=(b1+a1*i)%a2, y==b2 y=(b1+a1∗i), 本题有解故i不会超过a2。
y是最小解,则 y + l c m ( a 1 , a 2 ) ∗ × i y +lcm(a1, a2)*\times i y+lcm(a1,a2)∗×i都是解,故{lcm(a1,12), y}入栈。
扩展欧几里得(辗转相除发): a 1 x + b 1 = a 2 y + b 2 a1x + b1 = a2y + b2 a1x+b1=a2y+b2*方程式一 * *,方程式一的任意整数解(x1, y1)。a1x + b1就是答案。(a1x + b1)% lcm(a1, a2),如果 < 0,则加上lcm(a1, a2)。
方程式一就是 a 1 x − a 2 y = b 2 − b 1 a1x-a2y=b2-b1 a1x−a2y=b2−b1, 如果b2-b1不是gcd(a1, a2)的倍数,无解。
如果 a 1 x − a 2 y = g c d ( a 1 , a 2 ) a1x-a2y=gcd(a1, a2) a1x−a2y=gcd(a1,a2)方程式二的任意解(x1, y1), t = (b2 - b1) / gcd(a1, a2),(tx1, ty1)都方程式一的解。

代码

核心代码

#include<iostream>#include<sstream>#include<vector>#include<map>#include<unordered_map>#include<set>#include<unordered_set>#include<string>#include<algorithm>#include<functional>#include<queue>#include<stack>#include<iomanip>#include<numeric>#include<math.h>#include<climits>#include<assert.h>#include<cstring>#include<list>#include<array>#include<bitset>usingnamespace std;template<classT1,classT2> std::istream&operator>>(std::istream& in, pair<T1, T2>& pr){ in >> pr.first >> pr.second;return in;}template<classT1,classT2,classT3> std::istream&operator>>(std::istream& in, tuple<T1, T2, T3>& t){ in >>get<0>(t)>>get<1>(t)>>get<2>(t);return in;}template<classT1,classT2,classT3,classT4> std::istream&operator>>(std::istream& in, tuple<T1, T2, T3, T4>& t){ in >>get<0>(t)>>get<1>(t)>>get<2>(t)>>get<3>(t);return in;}template<classT1,classT2,classT3,classT4,classT5,classT6,classT7> std::istream&operator>>(std::istream& in, tuple<T1, T2, T3, T4,T5,T6,T7>& t){ in >>get<0>(t)>>get<1>(t)>>get<2>(t)>>get<3>(t)>>get<4>(t)>>get<5>(t)>>get<6>(t);return in;}template<classT=int> vector<T>Read(){int n; cin >> n; vector<T>ret(n);for(int i =0; i < n; i++){ cin >> ret[i];}return ret;}template<classT=int> vector<T>ReadNotNum(){ vector<T> ret; T tmp;while(cin >> tmp){ ret.emplace_back(tmp);if('\n'== cin.get()){break;}}return ret;}template<classT=int> vector<T>Read(int n){ vector<T>ret(n);for(int i =0; i < n; i++){ cin >> ret[i];}return ret;}template<int N =1'000'000>classCOutBuff{public:COutBuff(){ m_p = puffer;}template<classT>voidwrite(T x){int num[28], sp =0;if(x <0)*m_p++='-', x =-x;if(!x)*m_p++=48;while(x) num[++sp]= x %10, x /=10;while(sp)*m_p++= num[sp--]+48;AuotToFile();}voidwritestr(constchar* sz){strcpy(m_p, sz); m_p +=strlen(sz);AuotToFile();}inlinevoidwrite(char ch){*m_p++= ch;AuotToFile();}inlinevoidToFile(){fwrite(puffer,1, m_p - puffer,stdout); m_p = puffer;}~COutBuff(){ToFile();}private:inlinevoidAuotToFile(){if(m_p - puffer > N -100){ToFile();}}char puffer[N],* m_p;};template<int N =1'000'000>classCInBuff{public:inlineCInBuff(){}inline CInBuff<N>&operator>>(char& ch){FileToBuf();while(('\r'==*S)||('\n'==*S)||(' '==*S)){ S++;}//忽略空格和回车 ch =*S++;return*this;}inline CInBuff<N>&operator>>(int& val){FileToBuf();intx(0),f(0);while(!isdigit(*S)) f |=(*S++=='-');while(isdigit(*S)) x =(x <<1)+(x <<3)+(*S++^48); val = f ?-x : x; S++;//忽略空格换行 return*this;}inline CInBuff&operator>>(longlong& val){FileToBuf();longlongx(0);intf(0);while(!isdigit(*S)) f |=(*S++=='-');while(isdigit(*S)) x =(x <<1)+(x <<3)+(*S++^48); val = f ?-x : x; S++;//忽略空格换行return*this;}template<classT1,classT2>inline CInBuff&operator>>(pair<T1, T2>& val){*this>> val.first >> val.second;return*this;}template<classT1,classT2,classT3>inline CInBuff&operator>>(tuple<T1, T2, T3>& val){*this>>get<0>(val)>>get<1>(val)>>get<2>(val);return*this;}template<classT1,classT2,classT3,classT4>inline CInBuff&operator>>(tuple<T1, T2, T3, T4>& val){*this>>get<0>(val)>>get<1>(val)>>get<2>(val)>>get<3>(val);return*this;}template<classT=int>inline CInBuff&operator>>(vector<T>& val){int n;*this>> n; val.resize(n);for(int i =0; i < n; i++){*this>> val[i];}return*this;}template<classT=int> vector<T>Read(int n){ vector<T>ret(n);for(int i =0; i < n; i++){*this>> ret[i];}return ret;}template<classT=int> vector<T>Read(){ vector<T> ret;*this>> ret;return ret;}private:inlinevoidFileToBuf(){constint canRead = m_iWritePos -(S - buffer);if(canRead >=100){return;}if(m_bFinish){return;}for(int i =0; i < canRead; i++){ buffer[i]= S[i];//memcpy出错 } m_iWritePos = canRead; buffer[m_iWritePos]=0; S = buffer;int readCnt =fread(buffer + m_iWritePos,1, N - m_iWritePos,stdin);if(readCnt <=0){ m_bFinish =true;return;} m_iWritePos += readCnt; buffer[m_iWritePos]=0; S = buffer;}int m_iWritePos =0;bool m_bFinish =false;char buffer[N +10],* S = buffer;};classSolution{public:longlongAns(){longlong x =2022040920220409LL; stack<pair<longlong,longlong>> sta;for(int i =2; i <=49; i++){ sta.emplace(i,x % i);}while(sta.size()>1){auto[a, c]= sta.top(); sta.pop();auto[b, d]= sta.top(); sta.pop();for(longlong x=c;; x+=a ){if(x % b == d){ sta.emplace(lcm(a,b),x);break;}}}return sta.top().second;}};intmain(){#ifdef_DEBUGfreopen("a.in","r",stdin);#endif// DEBUG  ios::sync_with_stdio(0); cin.tie(nullptr);//CInBuff<> in; COutBuff<10'000'000> ob; //int N,K;//cin >>N>> K;#ifdef_DEBUG // printf("K=%d", K);// Out(a, ",a=");//Out(P, ",P=");/*Out(edge, ",edge="); Out(que, ",que=");*///Out(ab, ",ab=");//Out(par, "par=");//Out(que, "que=");//Out(B, "B=");#endif// DEBUG auto res =Solution().Ans(); cout <<res;return0;};

单元测试

TEST_METHOD(TestMethod1){auto res =Solution().Ans();AssertEx(2022040920220409LL, res);}

# 扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步ZEEKLOG学院,听白银讲师(也就是鄙人)的讲解。
https://edu.ZEEKLOG.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.ZEEKLOG.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

Read more

LeetCode128:哈希集合巧解最长连续序列

LeetCode128:哈希集合巧解最长连续序列

一、题目回顾 LeetCode 128 题「最长连续序列」是一道中等难度的数组题,核心要求如下:给定一个未排序的整数数组 nums,找出其中数字连续的最长序列(不要求序列元素在原数组中连续)的长度,且必须设计时间复杂度为 O (n) 的算法。 示例直观理解: * 输入 nums = [100,4,200,1,3,2],输出 4(最长序列是 [1,2,3,4]); * 输入 nums = [0,3,7,2,5,8,4,6,0,1],输出 9(完整连续序列 0-8)。 二、

By Ne0inhk
【设计模式】策略模式(Strategy)详解:把 if-else 变成可切换的算法

【设计模式】策略模式(Strategy)详解:把 if-else 变成可切换的算法

文章目录 * 1. 引言:if-else 正在失控 * 2. 什么是策略模式 * GoF 定义 * 3. 策略模式的核心思想 * 4. 策略模式的结构 * 5. 示例:商品价格计算 * 5.1 策略接口 * 5.2 具体策略 * 5.3 上下文 * 5.4 客户端使用 * 6. 策略模式的优点 * 7. 策略模式的缺点 * 8. 策略 vs 模板方法 * 9. JDK 中的策略模式 * Comparator * 10. 适用场景 * 11. 一个常见误区 * 参考 1. 引言:if-else 正在失控 在实际项目中,

By Ne0inhk
动态规划 线性 DP 五大经典模型:LIS、LCS、合唱队形、编辑距离 详解与模板

动态规划 线性 DP 五大经典模型:LIS、LCS、合唱队形、编辑距离 详解与模板

文章目录 * 最长上升子序列 * 【模板】最长上升子序列 * 合唱队形 * 牛可乐和最长公共子序列 * 编辑距离 经典线性 dp 问题有两个:最⻓上升⼦序列(简称:LIS)以及最⻓公共⼦序列(简称:LCS),这两道题⽬的很多⽅⾯都是可以作为经验,运⽤到别的题⽬中。⽐如:解题思路,定义状态表⽰的⽅式,推到状态转移⽅程的技巧等等。 因此,这两道经典问题是需要我们重点掌握的。 最长上升子序列 题目描述 题目解析 本题介绍最长上升子序列的一般解法,当数据量不大时用这种解法。 在此之前,小编先区分一下子数组和子序列,子数组需要是连续的,而子序列可以是间断的。 1、状态表示 dp[i]表示以i结尾的所有子序列中,最长的上升子序列。

By Ne0inhk
《算法题讲解指南:优选算法-双指针》--01移动零,02复写零

《算法题讲解指南:优选算法-双指针》--01移动零,02复写零

🔥小叶-duck:个人主页 ❄️个人专栏:《Data-Structure-Learning》 《C++入门到进阶&自我学习过程记录》 ✨未择之路,不须回头 已择之路,纵是荆棘遍野,亦作花海遨游 目录 一、双指针算法介绍   1、对撞指针   2、快慢指针 01、移动零 题目链接: 题目描述: 题目示例: 算法思路: 算法流程: C++ 代码演示: 算法总结: 02、复写零 题目链接: 题目描述: 题目示例: 算法思路: 算法流程: C++代码演示: 算法总结及流程解析: 结束语 一、双指针算法介绍       在正式讲解本次的算法题之前我们先来看看算法中一个非常常用的方法——双指针。双指针有两种形式,一种对撞指针,一种是左右指针。   1、对撞指针

By Ne0inhk