PAT:常见数学问题模板
Posted 花落,莫相离
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PAT:常见数学问题模板相关的知识,希望对你有一定的参考价值。
本文对PAT中常见数学问题用到的模板进行了归纳:
1.最大公约数与最小公倍数
int gcd(int a, int b){//求取最大公约数
return !b ? a : gcd(b, a%b);
}
int lcm(int a, int b){//求取最小公倍数
return a / gcd(a,b) * b; //先除后乘以避免溢出
}
2.分数
//注意,一般分数的分子分母用long long表示更保险,因为有时做运算时会导致int溢出
struct Fraction{//分数
int up, down; //分子与分母
};
Fraction reduction(Fraction result){//分数化简
if(result.down < 0){
result.up = - result.up;
result.down = -result.down;
}
if(!result.down) result.up = 1;
else{
int d = gcd(abs(result.up), abs(result.down)); //注意此处使用绝对值来求取最大公约数
result.up /= d;
result.down /= d;
}
return result;
}
void showResult(Fraction r){//分数输出
r = reduction(r);
if(r.down == 1) printf("%d", r.up);
else if(abs(r.up) > r.down)
printf("%d %d/%d", r.up/r.down, abs(r.up)%r.down, r.down);
else
printf("%d/%d", r.up, r.down);
}
3.素数
bool is_prime(int n){//判断素数
if(n <= 1) return false;
int sqrn = (int)sqrt(1.0 * n);
for(int i = 2; i <= sqrn; i++){//记住是从2开始,并且后面是小于等于号
if(n % i == 0) return false;
}
return true;
}
4.大整数运算
注意有负数时,先转换为正数,再确定最终的运算方式以及输出形式。
//大整数定义
struct bign{
int d[1000];
int len;
bign(){
memset(d, 0, sizeof(d));
len = 0;
}
};
//大整数转换
bign change(string str){
bign a;
a.len = str.size();
for(int i = 0; i < a.len; i++){
a.d[i] = str[a.len-1-i] - \'0\';
}
return a;
}
//大整数比较
int compare(bign a, bign b){
if(a.len > b.len) return 1;
else if(a.len < b.len) return -1;
else{
for(int i = a.len-1; i >= 0; i--){//注意从高位开始比较
if(a.d[i] > b.d[i]) return 1;
else if(a.d[i] < b.d[i]) return -1;
}
}
return 0;
}
//加
bign add(bign a, bign b){
bign c;
int carry = 0;
for(int i = 0; i < a.len || i < b.len; i++){
c.d[c.len++] = (a.d[i] + b.d[i] + carry) % 10;
carry = (a.d[i] + b.d[i] + carry) / 10;
}
if(carry) c.d[c.len++] = carry;
return c;
}
//减
bign sub(bign a, bign b){//减之前确保a要大于b,小于则交换位置,最后添加负号即可
bign c;
for(int i = 0; i < a.len || i < b.len; i++){
if(a.d[i] < b.d[i]){//不够减则借位
a.d[i+1]--;
a.d[i] += 10;
}
c.d[c.len++] = a.d[i] - b.d[i];
}
//去除前导零
while(c.len - 1 >= 1 && c.d[c.len - 1] == 0) c.len--;
return c;
}
//乘
bign multi(bign a, int b){
bign c;
int carry = 0;
for(int i = 0; i < a.len; i++){
c.d[c.len++] = (a.d[i] * b + carry) % 10;
carry = (a.d[i] * b + carry) / 10;
}
while(carry){
c.d[c.len++] = carry % 10;
carry /= 10;
}
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 < b) c.d[i] = 0; //不够除
else{
c.d[i] = r / b;
r = r % b;
}
}
//去除前导零
while(c.len - 1 >= 1 && c.d[c.len - 1] == 0) c.len--;
return c;
}
以上是关于PAT:常见数学问题模板的主要内容,如果未能解决你的问题,请参考以下文章
PAT Advanced 1132 Cut Integer (20) [数学问题-简单数学]
PAT Advanced 1049 Counting Ones (30) [数学问题-简单数学问题]