最大公约数的两种写法,运用的原来是欧几里得算法(即辗转相除法)
int gcd(int a,int b){
return !b?a:gcd(b,a%b);
}
int gcd(int a,int b){
if(b==0) return a;
else return gcd(b,a%b);
}
最小公倍数一般用 lcm(a,b) 表示,如果d为a和b的最大公约数,则最小公倍数为ab/d,
为了避免越界,最小公倍数最恰当的写法是a/d*b。由于d是a和b的最大公约数,因此a/d一定可以整除
PAT-B 1034. 有理数四则运算(20)
5.4 素数:
PAT-B 1007. 素数对猜想 (20)
PAT-B 1013. 数素数 (20)
对于一个正整数n来说,如果它存在1和它本身之外的银子,那么一定是在sqrt(n)的左右成对出现。如果它存在[2,n]范围内的质因子,要么这些质因子全部小于等于sqrt(n),要么只存在一个大于sqrt(n)的质因子,而其它质因子全部小于等于sqrt(n)
思路:
step1:枚举1~sqrt(n)范围内的所有质因子p,判断p是否为n的因子,如果是,就给fac数组中增加质因子p,并初始化个数为0,然后只要p还是n的因子,就让n不断除以p,每次操作令p的个数加1,直到p不再是n的因子为止
struct factor{
int x,cnt; //x为质因子,cnt为个数
}fac[10];
if(n%prime[i]==0){ //prime[i]是质数表数组
fac[num].x = prime[i]; //如果prime[i]是质因子,记录它
fac[num].cnt = 0;
while(n%prime[i]==0){ //计算出质因子prime[i]的个数
fac[num].cnt++;
n/=prime[i];
}
num++;
} //如果p不是n的因子,直接跳过
step2:如果上面步骤结束后n仍然大于1,说明n有且仅有一个大于sqrt(n)的质因子(也有可能是n本身),这时需要把这个质因子加入fac数组,并令其个数为1
if(n!=1){
fac[num].x = n;
fac[num++].cnt = 1;
}
PAT-B 1017. A除以B(20)
使用数组,数组中的每一位就代表了存放的每一位,而为了方便随时获取大整数的长度,一般都会定义一个int型变量len来记录其长度,并和d数组成结构体,并在结构体内部加上构造函数
struct bign{
int d[1000];
int len;
bign(){
memset(d,0,sizeof(d));
len=0;
}
};
输入大整数时,一般都是先用字符串读入,然后把字符串另存为至bign结构体。由于使用char数组进行读入时,整数的高位会变成数组的低位,而整数的低位会变成数组的高位,因此为了让整数在bign中顺位存储,需让字符串倒着赋给d[]数组
bign change(char str[]){
bign a;
a.len = strlen(str);
for(int i=0;i
如果要比较两个bign变量的大小:先判断长度,不相等则长的大;若相等,则从高位到低位进行比较,知道出现某一位不等
这样写法的条件是两个对象都是非负整数,如果有一方是负的,可以去掉负号,做高精度减法
bign add(bign a,bign b){
bign c;
int carry=0; //carry是进位
for(int i=0;i
//默认大减小
bign sub(bign a,bign b){
bign c;
for(int i=0;i=1 && c.d[c.len-1]==0){
c.len--; //去除高位的0,同时至少保留一位最低位
}
return c;
}
bign divide(bign a,int b,int& r){ //高精度除法,r为余数
bign c;
c.len = a.len;//被除数的每一位和商的每一位是一一对应的
for(int i=a.len-1;i>=0;i--){
r = r*10 + a.d[i];
if(r=1 && c.d[c.len-1]==0){
c.len--; //去除高位0
}
return c;
}
bign multi(bign a,bign b){
bign c;
int carry = 0;
for(int i=0;i