extend_gcd求解不定方程/膜线性方程/乘法(模)逆元
形如a*x+b*y=c
为不定方程,a,b>0其实无所谓,因为gcd(a,b)=gcd(|a|,|b|) //gcd为最大公约数
由数论的定理所知,当c%gcd==0,不定方程有解,现在我们来求这个解.
gcd=gcd(a,b);a*b=gcd*lcm; //lcm为最小公倍数
a'=a/gcd;b'=b/gcd;c'=c/gcd; a'目前与b'互质
令c''=1=a'*x+b'*y;
利用extend_gcd求出一组特解。(x0,y0)
(x0*c'.y0*c')为 a'*x+b'*y=c'的一组特解
由方程解的思想求出其通解;x=x0*c'+b'*t; y=y0*c'-a'*t;再用通解去求解题目
今天花了一晚上时间纠结了一个显而易见的问题。果然当局者迷。
我现在就想大笑一场。哈哈哈哈哈哈哈哈
UVA,10413
题目意思:t个case,n个野人,C,P,L分别代表初始洞穴,隔天移动洞穴数,存活天数。
问:最小的洞穴数,使得在n个野人在各自存活期不遇见。
数据:1*10^6 可以接受,所以此题以初值为野人中初始洞穴最大数,枚举就可以过了。
源代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 5 using namespace std; 6 7 int x,y,gcd,n; 8 int C[20],P[20],L[20]; 9 10 void extend_gcd(int a,int b) 11 { 12 if(b==0) 13 { 14 x=1; 15 y=0; 16 gcd=a; 17 return; 18 } 19 extend_gcd(b,a%b); 20 int tmp=x; 21 x=y; 22 y=tmp-a/b*y; 23 return; 24 } 25 26 bool solve(int i,int j,int m) 27 { 28 int c=C[i]-C[j]; 29 int b=m; 30 int a=P[j]-P[i]; 31 extend_gcd(a,b); 32 if(c%gcd) return false; 33 x*=c/gcd; 34 if(gcd<0) gcd=-gcd; 35 //因为x=x+b/gcd*k,所以x中包含了若干个b/gcd的代数和差 36 //因此用x对b/gcd取模,注意负数得x的最小正值 37 x=(x%(b/gcd)+b/gcd)%(b/gcd); 38 if(x<=L[i] && x<=L[j]) 39 return true; 40 return false; 41 } 42 bool test(int m) 43 { 44 for(int i=0;i<n-1;i++) 45 for(int j=i+1;j<n;j++) 46 { 47 if(solve(i,j,m)) return false; 48 } 49 return true; 50 } 51 52 53 int main() 54 { 55 int t; 56 scanf("%d",&t); 57 while(t--) 58 { 59 scanf("%d",&n); 60 int lb=0; 61 for(int i=0;i<n;i++) 62 { 63 scanf("%d %d %d",C+i,P+i,L+i); 64 lb=max(lb,C[i]); 65 C[i]--; 66 } 67 while(lb<=1000000) 68 { 69 if(test(lb)) break; 70 lb++; 71 } 72 printf("%d\n",lb); 73 } 74 return 0; 75 } 76 //提供测试数据 77 Sample Input 78 2 79 3 80 1 3 4 81 2 7 3 82 3 2 1 83 5 84 1 2 14 85 4 4 6 86 8 5 9 87 11 8 13 88 16 9 10 89 Sample Output 90 6 91 33
补充膜逆元//
a≡a^-1(mod n) 表示a同余n于a^-1 变式子:a*a^-1≡1(mod n) 即a^-1为a的膜逆元 有解的充分必要条件为a与n互质
若膜逆元存在,可以转换为a*b≡1(mod n)利用extend_gcd求不定方程的解来得到乘法逆元的通解。
a*b+n*y=1 extend_gcd(a,n) 解出一个b(mod n)取其最小值(正负特别考虑)
一般的:a*b+n*y=g a与n互质,g!=0则无解
因为:(a*b+n*y)(mod n)=g(mod n) a*b(mod n)=g(mod n)(g<n) g mod n !=1
则a*b!=1即b不是a的模逆元
欧拉定理中的模逆元
a与n为两个互质的正整数,a^f(n)≡1(mod n) f(n)为小于n且与n互质的正整数个数
a^f(n)=a*a^(f(n)-1)≡1(mod n)即a^(f(n)-1)为a的模n之逆元
中国剩余定理
x≡a1(mod m1)
x≡a2(mod m2)
...
x≡ai(mod mi)
m1,m2....mi互质,则对任意的a1,a2...ai方程组有解
且通解为:x=a1*t1*M1+a2*t2*M2+....+ai*ti*Mi+k*M (Mi=M/mi, M=m1*m2*...*mi)
具体证明及例子参考wiki
uva 11754
大致题意:
给你两个元素C,S C为行数,也代表互质元的个数,S代表要输入的最小的S个解。
接着的X,k为质数元,k代表要求的n对X取余之后的存在的余数个数,(这里n不唯一,所以对X有多个余数,
申明:一个数n对另一个数m取余数有且仅有一个)
具体想法:由于k为(1,100)当有C=9个k的时候dfs去搜的话会爆掉。
所以用特殊枚举法,当total=k[0]*k[1]*....*k[i]<10000的时候用dfs去搜
否则 找到一个基元s 用t*X[s]+Y[s][j]去枚举。 //这里s为当k/x最小的时候所取的值
//因为k越小,x越大,代表余数个数越小,除数越大,所以枚举所需要的次数越少。
//详细解释-重点: n=t*X[s]+Y[s][j] (t=0,1.....,)(j=0,1....k[s])因为n%X[s]=Y[s][j]。
//即无论要求多少个n,都能够从一个X[s]和其余数得出来。所以选择需要枚举次数最小的那一组(X[s],Y[s][j])(j=0,1...k[s])速度最快。
源代码://写了一下午,终于干掉了,进步了不少,继续加油!
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <set> 6 #include <vector> 7 8 using namespace std; 9 10 typedef long long ll; 11 const int maxc=15; 12 const int maxs=105; 13 const int limit=10000; 14 15 ll total; 16 int C,S,bestc; 17 int X[maxc],k[maxc],Y[maxc][maxs]; 18 19 void init() 20 { 21 total=1; 22 bestc=0; 23 for(int i=0;i<C;i++) 24 { 25 scanf("%d %d",&X[i],&k[i]); 26 total*=k[i]; 27 for(int j=0;j<k[i];j++) 28 scanf("%d",&Y[i][j]); 29 sort(Y[i],Y[i]+k[i]); 30 if(X[bestc]*k[i]<X[i]*k[bestc]) 31 bestc=i; 32 } 33 } 34 35 set<int> vis[maxc]; 36 void solveEnum(int s) 37 { 38 for(int i=0;i<C;i++) 39 { 40 if(i==s) 41 continue; 42 vis[i].clear(); 43 for(int j=0;j<k[i];j++) 44 vis[i].insert(Y[i][j]); 45 } 46 for(int t=0;S;t++) 47 { 48 for(int i=0;i<k[s];i++) 49 { 50 ll n=(ll)X[s]*t+Y[s][i]; 51 if(n==0) 52 continue; 53 bool flag=true; 54 for(int j=0;j<C;j++) 55 { 56 if(j==s) 57 continue; 58 if(!vis[j].count(n%X[j])) 59 { 60 flag=false; 61 break; 62 } 63 } 64 if(flag) 65 { 66 printf("%lld\n",n); 67 if(--S==0) 68 break; 69 } 70 } 71 } 72 } 73 74 void extend_gcd(ll a,ll b,ll& d,ll& x,ll& y) 75 { 76 if(!b) 77 { 78 x=1; 79 y=0; 80 d=a; 81 return; 82 } 83 extend_gcd(b,a%b,d,y,x); 84 y-=a/b*x; 85 return; 86 } 87 88 vector<int> sol; 89 int a[maxc]; 90 int China(int n,int* s,int* m) 91 { 92 ll M=1,d,y,x=0; 93 for(int i=0;i<n;i++) 94 M*=m[i]; 95 for(int j=0;j<n;j++) 96 { 97 ll w=M/m[j]; 98 extend_gcd(m[j],w,d,d,y); 99 x=(x+y*w*a[j])%M; 100 } 101 return (x+M)%M; 102 } 103 104 void dfs(int dep) 105 { 106 if(dep==C) 107 sol.push_back(China(C,a,X)); 108 else 109 { 110 for(int i=0;i<k[dep];i++) 111 { 112 a[dep]=Y[dep][i]; 113 dfs(dep+1); 114 } 115 } 116 } 117 118 void solveChina() 119 { 120 sol.clear(); 121 dfs(0); 122 sort(sol.begin(),sol.end()); 123 ll M=1; 124 for(int i=0;i<C;i++) 125 M*=X[i]; 126 for(int t=0;S;t++) 127 { 128 for(int j=0;j<sol.size();j++) 129 { 130 ll n = M*t+sol[j]; 131 if(n>0) 132 { printf("%lld\n",n); 133 if(--S==0) 134 break; 135 } 136 } 137 } 138 } 139 int main() 140 { 141 while(scanf("%d %d",&C,&S) == 2 && C+S) 142 { 143 init(); 144 if(total>limit) 145 solveEnum(bestc); 146 else 147 solveChina(); 148 puts("\n"); 149 } 150 return 0; 151 }
转载于:https://www.cnblogs.com/do-it-best/p/5335172.html
extend_gcd求解不定方程/膜线性方程/乘法(模)逆元相关推荐
- java乘法逆元与除法取模,逆元
题目描述 题目描述 求关于x的同余方程ax≡1(mod b)的最小正整数解. 输入格式 每组输入数据只有一行,包含两个正整数a, b,用一个空格隔开. 数据规模: 对于40%的数据,2≤b≤1,000 ...
- 如何利用扩展欧几里得算法求解不定方程_欧几里德算法、拓展欧几里德、中国剩余定理...
01.欧几里德算法(Euclidean algorithm)(辗转相除法) 欧几里德算法又称辗转相除法,主要是用于计算两个整数a,b的最大公约数. 简单点说一下算法原理:两个整数的最大公约数等于其中小 ...
- 【PTA】7-2 国王的奖励——分数取模、分治思想、快速幂、int64的乘法模运算【C/C++】
文章目录 1 问题 1.1 题面描述 1.2 输入描述 1.3 输出描述 1.4 样例描述 1.5 样例解释 2 分析 2.1 数学抽象 2.2 解决方法 2.2.1 等比求和 2.2.1.1 求和公 ...
- 【组合数学】生成函数 ( 使用生成函数求解不定方程解个数示例 2 | 扩展到整数解 )
文章目录 一.使用生成函数求解不定方程解个数示例 参考博客 : [组合数学]生成函数 简要介绍 ( 生成函数定义 | 牛顿二项式系数 | 常用的生成函数 | 与常数相关 | 与二项式系数相关 | 与多 ...
- 【组合数学】生成函数 ( 使用生成函数求解不定方程解个数示例 )
文章目录 一.使用生成函数求解不定方程解个数示例 参考博客 : [组合数学]生成函数 简要介绍 ( 生成函数定义 | 牛顿二项式系数 | 常用的生成函数 | 与常数相关 | 与二项式系数相关 | 与多 ...
- 【组合数学】生成函数 ( 使用生成函数求解不定方程解个数 )
文章目录 一.使用生成函数求解不定方程解个数 1.带限制条件 2.带系数 参考博客 : [组合数学]生成函数 简要介绍 ( 生成函数定义 | 牛顿二项式系数 | 常用的生成函数 | 与常数相关 | 与 ...
- Java黑皮书课后题第3章:*3.3(代数:求解2*2线性方程)编写程序,提示用户输入a、b、c、d、e和f,然后显示结果
*3.3(代数:求解2*2线性方程)编写程序,提示用户输入a.b.c.d.e和f,然后显示结果 题目 题目描述 运行示例 破题 代码 题目 题目描述 3.3(代数:求解22线性方程) 编写程序,提示用 ...
- 隔板法求解不定方程x1+x2+x3=5解的个数
隔板法求解不定方程的解的个数 文章目录 隔板法求解不定方程的解的个数 1.求正整数解的个数--普通隔板法 2.求非负整数解的个数--添加元素隔板法 1.求正整数解的个数--普通隔板法 将不定方程想象成 ...
- 组合数学 —— 组合数取模 —— 逆元与递推打表
[逆元求法] 1.要求:p 是质数 2.时间复杂度:O(n) 3.求解 的步骤: 1)通过循环,预先算好所有小于 N 的阶乘(%p)的结果,存到数组 fac[] 中 (fac[i] = i!%p) ...
最新文章
- 用Python偷偷告诉你十一假期8亿人都去哪儿浪?
- AngularJS 1.x 国际化——Angular-translate例子
- scanf格式控制符
- web和mysql连接并增删改查_Java Web 使用IDEA对mysql数据库进行简单增删改查操作(附源码下载)...
- tf卡量产工具万能版_新物1TB TF卡正式开卖!容量大得惊人,售价也同样不菲
- Mysql从库主键卡住_从库宕机引发的主键冲突
- Linux比较大文件内容,Linux系统最大文件打开数优化,解决Too many open files报错
- ccs10怎么导入工程文件_FCPX导入位置选项时如何使用!
- IDC MarketScape:华为云IoT物联网平台位居领导者象限
- Android源码分析之Builder模式
- DiskFileUpload类
- springboot中学成绩管理毕业设计源码100854
- visio2013里画带箭头的折线连接线
- 自己建设网站需要学习什么?
- 2021-07-11 layer与tier的区别(英语)
- 2017年的博客之路开始---下一个十年
- NLog NETCore 3.0 Porting
- SPA 项目 之 后台接口文档
- 定制xdoclet 标签
- Go语言Seelog入门
热门文章
- 计算机网络封装过程图,网络传输过程是怎样的?网络数据传输的过程图解
- java hook全局钩子,牛逼骚操作:Java 虚拟机关闭钩子(Shutdown Hook)!
- source insight 4.0 无法同步文件问题
- TensorFlow从1到2 | 第五章 非专家莫入!TensorFlow实现CNN
- centos 安装mysql_Centos 下mysql数据库完整安装过程
- 英语c开头语言,字母c开头的英语短语
- mysql罏在十三_MySQL高级知识(十三)——表锁
- 2016版系统集成项目管理工程师考试题型举例
- 【链接】 一篇很好的有关卡特兰数的博文
- SpringBoot 2.0 Actuator监控系统