5.1 简单数学
For any 4-digit integer except the ones with all the digits being the same, if we sort the digits in non-increasing order first, and then in non-decreasing order, a new number can be obtained by taking the second number from the first one. Repeat in this manner we will soon end up at the number 6174
-- the black hole of 4-digit numbers. This number is named Kaprekar Constant.
For example, start from 6767
, we'll get:
7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174
7641 - 1467 = 6174
... ...
Given any 4-digit number, you are supposed to illustrate the way it gets into the black hole.
Input Specification:
Each input file contains one test case which gives a positive integer N in the range (.
Output Specification:
If all the 4 digits of N are the same, print in one line the equation N - N = 0000
. Else print each step of calculation in a line until 6174
comes out as the difference. All the numbers must be printed as 4-digit numbers.
Sample Input 1:
6767
Sample Output 1:
7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174
Sample Input 2:
2222
Sample Output 2:
2222 - 2222 = 0000
#include<cstdio> #include<algorithm> using namespace std; bool cmp(int a,int b){ return a > b; } void toarray(int n,int num[]){ for(int i=0;i<4;i++){ num[i] = n%10; n /= 10; } } int tonumber(int num[]){ int sum = 0; for(int i=0;i<4;i++){ sum = sum*10 + num[i]; } return sum; } int main(){ int n; scanf("%d",&n); int num[5]; while(1){ int max1,min1; toarray(n,num); sort(num,num+4); min1 = tonumber(num); sort(num,num+4,cmp); max1 = tonumber(num); n = max1 - min1; printf("%04d - %04d = %04d ",max1,min1,n); if(n==6174 || n==0){ break; } } return 0; }
5.2 最大公约数与最小公倍数
5.2.1 最大公约数
1818: 最大公约数
题目描述
输入两个正整数,求其最大公约数。
输入
测试数据有多组,每组输入两个正整数。
输出
对于每组输入,请输出其最大公约数。
样例输入
49 14
样例输出
7
#include<cstdio> int gcd(int a,int b){ if(b == 0) return a; else return gcd(b,a%b); } int main(){ int m,n; while(scanf("%d%d",&m,&n)!=EOF){ printf("%d ",gcd(m,n)); } return 0; }
5.3 分数的四则运算
5.3.1 分数的表示和化简
1.分数的表示
struct Fraction{
int up,down;
};
规定:
①使down为非负数。如果分数为负,那么令分子up为负即可。
②如果该分数恰为0,那么规定其分子为0,分母为1.
③分子和分母没有除了1以外的公约数。
2.分数的化简
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; }
5.3.2 分数的四则运算
1.分数的加法
Fraction add(Fraction f1,Fraction f2){ Fraction result; result.up = f1.up * f2.down + f2.up*f1.down; result.down = f1.down * f2.down; return reduction(result); }
2.分数的减法
Fraction minu(Fraction f1,Fraction f2){ Fraction result; result.up = f1.up * f2.down - f2.up*f1.down; result.down = f1.down * f2.down; return reduction(result); }
3.分数的乘法
Fraction multi(Fraction f1,Fraction f2){ Fraction result; result.up = f1.up * f2.up; result.down = f1.down * f2.down; return reduction(result); }
4.分数的除法
Fraction divide(Fraction f1,Fraction f2){ Fraction result; result.up = f1.up * f2.down; result.down = f1.down * f2.up; return reduction(result); }
只有当除数不为0时,才能用上面的函数进行计算。
5.3.3 分数的输出
void showResult(Fraction r){ r = reduction(r); if(r.down == 1){ printf("%lld",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); } }
5.4 素数
素数又称为质数,是指除了1和本身之外,不能被其他数整除的一类数。1既不是素数,也不是合数。
5.4.1 素数的判断
bool isPrime(int n){ if(n <= 1) return false; int sqr = (int)sqrt(1.0*n); for(int i=2;i<=sqr;i++){ if(n % i == 0) return false; } return true; }
sqrt的作用为一个浮点数开根号,需要添加math.h头文件。
5.4.2 素数表的获取
const int maxn = 101; //表长 int prime[maxn],pNum = 0; //prime数组存放所有素数,pNum为素数个数 bool p[maxn] = {0}; //p[i] == true表示i是素数 void Find_Prime(){ for(int i=1;i<maxn;i++){ if(isPrime(i) == true){ prime[pNum++] = i; p[i] = true; } } }
埃氏筛法:
例子:求1~15中的所有素数
PAT B1013 数素数 (20分)
令 Pi 表示第 i 个素数。现任给两个正整数 M≤N≤104,请输出 PM 到 PN 的所有素数。
输入格式:
输入在一行中给出 M 和 N,其间以空格分隔。
输出格式:
输出从 PM 到 PN 的所有素数,每 10 个数字占 1 行,其间以空格分隔,但行末不得有多余空格。
输入样例:
5 27
输出样例:
11 13 17 19 23 29 31 37 41 43
47 53 59 61 67 71 73 79 83 89
97 101 103
#include<cstdio> #include<cmath> const int maxn = 10010; long long prime[maxn]; bool isPrime(int a){ for(int i=2;i<=sqrt(a);i++){ if(a % i == 0){ return false; } } return true; } int main(){ int m,n; scanf("%d%d",&m,&n); int num = 1; for(int i=2;num<=n;i++){ if(isPrime(i)==true){ prime[num++] = i; } } int count=0; for(int i=m;i<=n;i++){ printf("%d",prime[i]); count++; if(count %10!=0 && i<n) printf(" "); else printf(" "); } return 0; }
5.5 质因子分解
所谓质因子分解是指将一个正整数n写成一个或多个质数的乘积形式,例如6 = 2 * 3,8 = 2 * 2 * 2,180 = 2 * 2 * 3 *3 *5。
定义结构体factor,用来存放质因子及其个数,如下所示:
struct factor{
int x,cnt;
}fac[10];
例如对180来说,fac数组如下:fac[0].x = 2; fac[0].cnt = 2; fac[1].x = 3; fac[1].cnt = 2; fac[2].x = 5;fac[2].cnt = 1;
PAT A1059 Prime Factors (25分)
Given any positive integer N, you are supposed to find all of its prime factors, and write them in the format N = p1k1×p2k2×⋯×pmkm.
Input Specification:
Each input file contains one test case which gives a positive integer N in the range of long int.
Output Specification:
Factor N in the format N =
p1^
k1*
p2^
k2*
…*
pm^
km, where pi's are prime factors of N in increasing order, and the exponent ki is the number of pi -- hence when there is only one pi, ki is 1 and must NOT be printed out.
Sample Input:
97532468
Sample Output:
97532468=2^2*11*17*101*1291
#include<cstdio> #include<cmath> bool isprime(int n){ if(n<=1){ return false; } int sqr = (int)sqrt(1.0*n); for(int i=2;i<=sqr;i++){ if(n%i == 0) return false; } return true; } const int maxn = 100010; int prime[maxn],pNum=0; void Find_Prime(){ for(int i=1;i<maxn;i++){ if(isprime(i)){ prime[pNum++] = i; } } } struct factor{ int x; int cnt; }fac[10]; int main(){ Find_Prime(); int n,num=0; scanf("%d",&n); if(n==1){ printf("1=1 "); }else{ printf("%d=",n); int sqr = (int)sqrt(n*1.0); for(int i=0;i<pNum && prime[i]<=sqr;i++){ if(n % prime[i]==0){ fac[num].x = prime[i]; fac[num].cnt = 0; while(n%prime[i]==0){ fac[num].cnt++; n /= prime[i]; } num++; if(n == 1) break; } } if(n != 1){ fac[num].x = n; fac[num++].cnt = 1; } } for(int i=0;i<num;i++){ if(i > 0) printf("*"); printf("%d",fac[i].x); if(fac[i].cnt>1) printf("^%d",fac[i].cnt); } return 0; }
5.6 大整数运算
5.6.1 大整数的存储
使用数组存储大整数即可,例如定义int型数组d[1000],那么这个数组中的每一位就代表了存放的整数的每一位。如将整数235813存储到数组中,
则有d[0]=3, d[1]=1, d[2]=8, d[3]=5 ,d[4]=3, d[5]=2,即整数的高位存储在数组的高位,整数的低位存储在数组的低位。但是把整数按字符串%s读入的时候,实际上是逆味存储的,即str[0] = ‘2',
str[1] = '3' ...,因此在读入之后需要在另存为至d[]数组的时候反转一下。
会定义一个int型变量len来记录长度,并和d数组组合成结构体。
struct bign{
int d[1000];
int len;
bign(){
memset(d,0,sizeof(d));
len = 0;
}
};
将字符串转换为bign结构体
bign change(char str[]){ bign a; a.len = strlen(str); for(int i=0;i<a.len;i++){ a.d[i] = str[a.len - i -1] - '0'; } return a; }
比较两个bign变量的大小
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; } }
5.6.2 大整数的四则运算
bign add(bign a,bign b){ bign c; int carry = 0; for(int i=0;i<a.len || i<b.len;i++){ int temp = a.d[i] + b.d[i] + carry; c.d[c.len++] = temp % 10; carry = temp / 10; } if(carry != 0){ c.d[c.len++] = carry; } return c; }
bign sub(bign a,bign 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++){ int temp = a.d[i]*b + carry; c.d[c.len++] = temp%10; carry = temp/10; } while(carry != 0){ c.d[c.len++] = carry % 10; carry /= 10; } return c; }
bign divide(bign a,int b,int &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; }
5.7 扩展欧几里得算法