ACM-韩信点兵【中国剩余定理-孙子定理】
2016-05-02 21:02
211 查看
题目34---韩信点兵
时间限制:3000 ms | 内存限制:65535 KB
难度:1
描述
相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入3个非负整数a,b,c ,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100 。
输入
输入3个非负整数a,b,c ,表示每种队形排尾的人数(a<3,b<5,c<7)。例如,输入:2 4 5
输出
输出总人数的最小值(或报告无解,即输出No answer)。实例,输出:89
样例输入
2 1 6样例输出
41
我的答案:
#include<iostream>
标准答案如下:
这道题用的是中国剩余定理,也称孙子定理从而简化了代码,提高了程序的效率。
其实这道题简化为已知三个互质的数A,B,C除某个数X的余数a,b,c和这三个互质的数,求这个X的最小值
如果写成数学公式就是:
X%A=a;
X%B=b;
X%C=c;
解决问题的方法是首先求出一个尽可能小的数 Y ,使得Y分别除以三个质数时,得到的余数恰好为a,b,c。然后Y再除以三个互质的数的最小公倍数G,余数即为X。
所以首先要找到这个数Y:
找到这个数Y的方法是先找到三个数M,N,P:M分别除以三个质数时,得到的余数为a,0,0;N时,余数为0,b,0;P时,余数为0,0,c。
如此,Y = M+N+P。就可以得到想要的Y。
然后是找到数M,N,P的方法:
这里举例找数M的方法,其它同理:若要使M%B==M%C=0、M%A=a,则M必为B与C的公倍数
所以先求出B与C的公倍数T,然后用T和T的倍数与A相除,直到找到余数为1的较小值Q(不必要求是最小值,只是尽量小方便运算),则M = Q*a;
同理找出另外两个较小值R,F,则N=R*b,P=F*c。
所以Y=Q*a+R*b+F*c;
则X=(Q*a+R*b+F*c)%G;
当互质的数的数量变为4个,5个,6个,余数有变化等情况,皆可运用上述定理。
PS:
1 注意题目是否有解,数与数之间必须互质
2 如果数与数之间非互质,则必须符合实际情况,如 3除余2,9除余4的条件是不可能的,因为9除余4,3除4余1,而不是余2,则题目不成立。
3 G必须为最小公倍数
题目34---韩信点兵
时间限制:3000 ms | 内存限制:65535 KB
难度:1
描述
相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入3个非负整数a,b,c ,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100 。
输入
输入3个非负整数a,b,c ,表示每种队形排尾的人数(a<3,b<5,c<7)。例如,输入:2 4 5
输出
输出总人数的最小值(或报告无解,即输出No answer)。实例,输出:89
样例输入
2 1 6样例输出
41
我的答案:
#include<iostream>
using namespace std;
int hanxindianbing(int a,int b,int c){
for(int i = 7+c; i <100;i=i+7)
{
if(i%3==a&&i%5==b)
return i;
}
return 0;
}
int main(){
while (1){
int a,b,c;
cin>>a>>b>>c;
if(a<3&&b<5&&c<7)
cout<<hanxindianbing(a,b,c)<<endl;
}
}
标准答案如下:
01.
#include<iostream>
02.
using
namespace
std;
03.
int
main()
04.
{
05.
int
a,b,c;
06.
cin>>a>>b>>c;
07.
int
n=(a*70+b*21+c*15)%105;
08.
if
(n>100||n<10) cout<<
"No answer"
<<endl;
09.
else
cout<<n<<endl;
10.
}
这道题用的是中国剩余定理,也称孙子定理从而简化了代码,提高了程序的效率。
其实这道题简化为已知三个互质的数A,B,C除某个数X的余数a,b,c和这三个互质的数,求这个X的最小值
如果写成数学公式就是:
X%A=a;
X%B=b;
X%C=c;
解决问题的方法是首先求出一个尽可能小的数 Y ,使得Y分别除以三个质数时,得到的余数恰好为a,b,c。然后Y再除以三个互质的数的最小公倍数G,余数即为X。
所以首先要找到这个数Y:
找到这个数Y的方法是先找到三个数M,N,P:M分别除以三个质数时,得到的余数为a,0,0;N时,余数为0,b,0;P时,余数为0,0,c。
如此,Y = M+N+P。就可以得到想要的Y。
然后是找到数M,N,P的方法:
这里举例找数M的方法,其它同理:若要使M%B==M%C=0、M%A=a,则M必为B与C的公倍数
所以先求出B与C的公倍数T,然后用T和T的倍数与A相除,直到找到余数为1的较小值Q(不必要求是最小值,只是尽量小方便运算),则M = Q*a;
同理找出另外两个较小值R,F,则N=R*b,P=F*c。
所以Y=Q*a+R*b+F*c;
则X=(Q*a+R*b+F*c)%G;
当互质的数的数量变为4个,5个,6个,余数有变化等情况,皆可运用上述定理。
PS:
1 注意题目是否有解,数与数之间必须互质
2 如果数与数之间非互质,则必须符合实际情况,如 3除余2,9除余4的条件是不可能的,因为9除余4,3除4余1,而不是余2,则题目不成立。
3 G必须为最小公倍数
相关文章推荐
- C++基础实例-结构类型(3)
- <!DOCTYPE html>很重要
- Html5 Egret游戏开发 成语大挑战(九)设置界面和声音管理
- Ubuntu16.04(64bit)安装YouCompleteMe
- 重构:Move Method
- HDU 2036 改革春风吹满地(求多边形面积)
- 推荐系统概述
- Kafka设计解析(三)- Kafka High Availability (下)
- 关于static的使用
- Qt XML数据解析
- C++大数问题
- 我爱学Java之中间缓存变量机制
- 复杂链表的复制
- Linux下安装配置Apache+PHP+MariaDB
- VS编译生成MATLAB接口程序
- struts2入门2--参数的传递
- hdu1257 最少拦截系统
- MAC安装Windows双系统
- DES加密解密->java实现
- GetWindowRect和GetClientRect的区别详解