一、简单数学 PATB1019
PATB1019
注意点:一个是输出格式,均为4位整数,最高位补0,此时的技巧是利用printf的格式化输出 %04d
另一个还是输出格式,仔细看PAT的样例,存在空格
#include<stdio.h>
#include<algorithm>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
void num_to_array(int number,int a[])
{
for(int i=0;i<4;i++)
{
a[i]=number%10;
number/=10;
}
}
int array_to_num(int a[])
{
int number=0;
for(int i=3;i>=0;i--)
{
number=number*10+a[i];
}
return number;
}
int main()
{
int number1,number2,result,a[10];
int i;
scanf("%d",&number1);
while(1)
{
num_to_array(number1,a);
sort(a,a+4,cmp);
number1=array_to_num(a);
sort(a,a+4);
number2=array_to_num(a);
if(number1==number2)
{
printf("%04d - %04d = 0000\n",number1,number2);
break;
}
else
{
result=number2-number1;
printf("%04d - %04d = %04d\n",number2,number1,result);
if(result==6174) break;
else
{
number1=result;
}
}
}
}
二、最大公因数和最小公倍数
对于最大公因数,作者提供了一个极其精妙的递归写法:
利用递归写法,还无需考虑a和b哪个大
#include<stdio.h>
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
int main()
{
int m,n;
scanf("%d%d",&m,&n);
printf("%d",gcd(m,n));
}
对于最小公倍数,[a,b]=ab/(a,b)
但保存ab时候会超时,因此利用一个常用技巧
a/(a,b) * b
三、分数化简 运算 输出
其中分数化简是需要关注的
分数化简只要记住三条原则:
- 分子为0时,分母设置为1
- 如果分母为负,则分子分母都取相反数,让分母化为正
- 分子分母同除最大公约数,实现约分 (此处要注意取绝对值)
分数输出的原则: - 分母down为1,以整数形式输出
- 假分数 以带分数形式输出 (此处也要注意取绝对值)
#include <stdio.h>
#include <math.h>
struct Fraction
{
int up;
int down;
};
int gcd(int a, int b)
{
if (b == 0)
return a;
else
return gcd(b, a % b);
}
Fraction reduction(Fraction result)
{
if (result.down < 0)
{
result.up = -result.up;
result.down = -result.down;
}
if (result.up == 0)
result.down = 1;
else
{
int d = gcd(abs(result.up), abs(result.down)); //注意点:需要取绝对值
result.up /= d;
result.down /= d;
}
return result;
}
//分数输出
//分母down为1,以整数形式输出
//假分数 以带分数形式输出 ->一定要关注绝对值的使用
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);
}
四、素数判断
#include<stdio.h>
#include<math.h>
bool isPrime(int n)
{
if(n<=1) return false;
int sqr=(int)sqrt(n*1.0); //sqrt的参数为浮点型,返回值也为浮点型
for(int i=2;i<=sqr;i++)
{
if(n%i==0) return false;
}
return true;
}
//写法2:n接近int型变量上界时会导致i*i溢出 n<10^9范围内安全
bool isPrime2(int n)
{
if(n<=1) return false;
//定义 long long i 就不怕溢出啦
for(int i=2;i*i<=n;i++)
{
if(n%i==0) return false;
}
return true;
}
五、1~n的素数表
有了之前的判断素数,其实已经有了一个直观的想法,直接遍历一个个判断即可
复杂度为O(n√n) 而这个复杂度对n<10^5的大小是没有问题的
int prime[100];
bool p[100]={false};
int Find_Prime(int n)//1~n素数表,返回值为素数个数
{
int i;
int num=0;
for(i=1;i<=100;i++)
{
if(isPrime(i))
{
prime[num++]=i;
p[i]=true;
}
}
return num;
}
int main()
{
int num=Find_Prime(100);
// printf("%d ",num);
int i;
for(i=0;i<num;i++)
{
printf("%d ",prime[i]);
}
}
利用埃氏筛法,可以将时间复杂度降到O(n)
事先需要确定2为素数
注意点:在给p数组赋值时,可以全部赋值为0/false,但无法“简单地”全赋值为1/true
正确:int p[101]={0};
错误:int p[101]={1};
实际上只有第一个元素p[0]被赋值为1
#include<stdio.h>
int p[101]={0};
int prime[101];
int FindPrime()
{
int i,j;
int num=0;
for(i=2;i<101;i++)
{
if(p[i]==0)
{
prime[num++]=i;
for(j=i+i;j<101;j+=i)
{
p[j]=1; //标记为1,说明不是素数,被筛去
}
}
}
return num;
}
int main()
{
int i;
int num=FindPrime();
for(i=0;i<num;i++)
{
printf("%d ",prime[i]);
}
}