hdu 1573(数论:中国剩余定理)
来源:互联网 发布:忽略此网络后怎么恢复 编辑:程序博客网 时间:2024/06/05 07:27
网上都说这个题用中国剩余定理做,但是中国剩余定理的适用条件是:
求解x=a[i](mod n[i])方程组,且n[i]两两互质
但可以发现这个题中n[i]并不两两互质
想不出解法参考网上的代码发现好多人都是用暴力写的,偏偏说是中国剩余定理
我就对着用暴力写了一个,但是暴力的过程需要优化处理,否则会超时
另外从这道题中也学会了怎么求解多个数的最小公倍数
1、求解最小公倍数(lcm)方法:
之前做题求两个数的lcm时,都是用其乘积除以它们的gcd
于是这次就很自然的这么做,才发现这样做的方法错得很离谱
比如:求2 3 4的lcm 答案很明显是12
但是用上述方法求得出来的结果是1
所以正确的方法应该是每次求出当前结果与下一个数的lcm
如果想要一次求出所有数的lcm,正确的做法如下:
如求a[1-n]的lcm
令M=a[i]*...*a[n];
令b[i]=M/a[i]; b_gcd为b数组的gcd
则a数组的lcm为M/b_gcd
用第一种方式写出来的代码会更简洁些:
for(int i=0; i<num; ++i) { scanf("%d", &a[i]); lcm = lcm*a[i]/gcd(lcm, a[i]);}
2、中国剩余定理
发现网上很多人说中国剩余定理的变形可以用来解决n[i]两两不互质的情况
因为感觉太繁琐了,又是模板型,就没有看,下面把普通的中国剩余定理代码贴上
#include <cmath>#include <cstdio>#include <iostream>#include <algorithm>#define MAXN 10010#define LL long longusing namespace std;int a[MAXN], n[MAXN], m[MAXN];int gcd(int a, int b) { return b==0 ? a : gcd(b, a%b);}int expand_gcd(int a, int b, int d, int &x, int &y) {//用于求ax+by=d的一个解 if(b == 0) { d = a; x = 1; y = 0; } else { expand_gcd(b, a%b, d, y, x); y -= x*(a/b); }}int inv(int a, int n) {//用于求逆元 int d, x, y; expand_gcd(a, n, d, x, y); return d==1 ? (x+n)%n : -1;}int chinese_remainder(int a[], int n[], int num) { int M = 1; int d, x, y; for(int i=1; i<=num; ++i) { M *= n[i]; } int sum = 0; for(int i=1; i<=num; ++i) { m[i] = M/n[i]; expand_gcd(m[i], -n[i], d, x, y); x = inv(m[i], -n[i]); sum += (a[i]*x*m[i])%M; } return sum % M;}int main(void) { int num; while(scanf("%d", &num) != EOF) { for(int i=1; i<=num; ++i) { scanf("%d %d", &a[i], &n[i]); } cout << chinese_remainder(a, n, num) << endl; } return 0;}
看到了一个很好的中国剩余定理对应n[i]非两两互质的说明
把图片传在这里
3、这道题的代码:
找到第一个i满足模方程组后,可知i+k*lcm均满足条件(k为非负数)
从这个形式可以发现第一个满足条件的一定是i 且i<=lcm
故在找i的for循环中可以限定条件i<=lcm,这样会大大优化程序运行时间
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAXN 10#define LL long longusing namespace std;int a[MAXN], b[MAXN];int gcd(int a, int b) { return b==0 ? a : gcd(b,a%b);}int main(void) { int T; int lcm; bool flag; scanf("%d", &T); while(T--) { int max, num; scanf("%d%d", &max, &num); lcm = 1; flag = false; for(int i=0; i<num; ++i) { scanf("%d", &a[i]); lcm = lcm*a[i]/gcd(lcm, a[i]); } for(int i=0; i<num; ++i) { scanf("%d", &b[i]); } int i = 0, j; for(i=1; i<=max && i<=lcm; ++i) { for(j=0; j<num; ++j) { if(i%a[j] != b[j]) { break; } } if(j == num) { flag = true; break; } } if(!flag) cout << "0" << endl; else { cout << (max-i)/lcm+1 << endl; } } return 0;}
0 0
- hdu 1573(数论:中国剩余定理)
- HDU 1573 X问题 数论-(中国剩余定理)
- HDU 5768 Lucky7 数论 中国剩余定理
- 数论-中国剩余定理
- 数论/中国剩余定理
- 【数论】中国剩余定理
- 中国剩余定理【数论】
- 数论--中国剩余定理
- hdu-1573(中国剩余定理)
- hdu 1573 中国剩余定理
- hdu 1573 中国剩余定理
- [数论]中国剩余定理 CRT
- HDU 中国剩余定理
- hdu 1573 X问题 中国剩余定理
- hdu 1573(中国剩余定理)
- hdu 1573 X问题(中国剩余定理)
- (中国剩余定理) hdu 1573 X问题
- HDU 1573 X问题 中国剩余定理
- 2014.7.7 模拟赛【小K的农场】
- MySQL实现Oracle中rownum批量更新行ID
- C++与Java的语法区别
- 一份很完善的文件上传
- Hie with the Pie - POJ 3311 状压dp
- hdu 1573(数论:中国剩余定理)
- 提示:Not targeting the latest versions of Android; compatibility modes apply. .....
- 小白鼠与毒药
- IC Design 之设计流程和工具
- ubuntu 14.04 spark单机平台搭建
- rcp(插件开发) 如何使用插件下的Log日志
- 用NPAPI开发跨浏览器的插件,解决浏览器兼容问题
- Android OTA 与recovery模块代码解析
- 日志收集之flume-ng源码分析