PAT第五章专题复习

PAT第五章专题复习

  • 数学题

    • A 1049 :统计从1-N中1的个数

      • 思路:

        ①逐位进行考虑。从低位开始,如果当前位now = 0的话,就只需要考虑左边部分的个数。表达式为ans += left * a;

        ②如果now = 1的话,左边部分计算同理;now位有1个,再加上右边部分的数值。可以得到表达式为ans += left * a + 1 + right

        ③如果now >= 2的话,没有任何限制,可以得到表达式ans += (left + 1) * a;

      • 代码实现

        #include<bits/stdc++.h>
        using namespace std; 
        int main(){
        	int n;
        	cin >> n;
        	int left, right, now;
        	int a = 1; //10的多少次方
        	int ans = 0; //记录1的个数
        	while(n/a != 0){//总共有多少位 
        		left = n / (a * 10);//当前位左边部分的数
        		right = n % a;//当前位右边部分的数
        		now = n / a % 10; //当前位上的数
        		//分三种情况
        		if(now == 0)ans += left * a;
        		else if(now == 1)ans += left * a + right + 1;
        		else ans += (left + 1) * a;
        		a *= 10; 
        	} 
        	printf("%d\n", ans);
        	return 0;
        } 
        
  • 分数运算

    • 需要注意答案为0时候的输出。容易犯下0/1类似的错误。

    • A 1088 计算分数的加减乘除运算

      • 思路:

        ①难点在于如何精简写代码。要熟练运用三目运算符。

        ②调用的func函数中,首先判断,分子分母是否为0,如果分母为0,输出inf;如果分子为0,输出0;满足任意两者都直接return,不用再进行后续操作。

        ③接着,判断分子与分母是否异号,注意判断的时候不能用m*n<0这样直白来判断,会导致数据过大溢出,符号发生改变。如果为异号,就利用三目运算符输出"(-",否则输出一个空字符串。

        ④然后求真分数整数部分值,输出。接着判断是否还存在分数部分,如果不存在,且分子分母异号,输出“)”后return返回。如果存在,再接着求解最大公因子,约分输出。

      • 代码实现

        #include<bits/stdc++.h>
        using namespace std;
        long long a, b, c, d;
        long long gcd(long long t1, long long t2){
        	if(t2 == 0)return t1;
        	else return gcd(t2, t1 % t2);
        }
        //化简并打印函数 
        void func(long long m, long long n){
        	if(m * n == 0){
        		printf("%s", n == 0? "Inf":"0");
        		return;
        	}
        	//注意以下不能写成m*n<0,会溢出然后变成正数 
        	bool flag = ((m < 0 && n > 0) || (m > 0 && n < 0));
        	m = abs(m), n = abs(n);
        	long long x = m / n;
        	printf("%s", flag ? "(-" : "");
        	if(x != 0)printf("%lld", x);
        	if(m % n == 0){
        		if(flag)printf(")");
        		return;
        	}
        	if(x != 0)printf(" ");
        	m = m - x * n;
        	long long t = gcd(m, n);
        	m = m / t, n = n / t;
        	printf("%lld/%lld%s", m, n, flag ? ")" : "");
        }
        int main(){
        	scanf("%lld/%lld %lld/%lld", &a, &b, &c, &d);
        	//加法 
        	func(a, b);printf(" + ");func(c, d);
        	printf(" = ");func(a * d + b * c, b * d);printf("\n");
        	//减法 
        	func(a, b);printf(" - ");func(c, d);
        	printf(" = ");func(a * d - b * c, b * d);printf("\n");
        	//乘法
        	func(a, b);printf(" * ");func(c, d);
        	printf(" = ");func(a * c, b * d);printf("\n");
        	//除法
        	func(a, b);printf(" / ");func(c, d);
        	printf(" = ");func(a*d, b * c); 
        	
        	return 0;
        } 
        
  • 素数

    • A 1015 :一个十进制数和它的某一特定进制数反转后转换为的十进制数,两个数是否都是素数。

      • 本题有两个坑,一个是题意,不是直接判断d进制数是否为素数,而是仍然要将反转的d进制数再转换为十进制数,然后判断是否为素数。 第二个就是0和1不是素数。求素数问题时,都要注意这一点

      • 代码实现

        #include<bits/stdc++.h>
        using namespace std;
        int a[1000006];
        bool judge(long long n){
        	//注意0和1不是素数,需要写在判断函数里 
        	if(n <= 1)return false;
        	long long sqr = (long long)sqrt(n * 1.0);
        	for(long long i = 2; i <= sqr; i++){
        		if(n % i == 0){
        			return false;
        		}
        	}
        	return true;
        }
        long long change(int b[], int n, int d){
        	int index = 0;
        	long long num1 = 0;
        	do{
        		b[index++] = n % d;
        		n /= d;
        	}while(n != 0)
        	for(int i = 0; i < index; i++){
        		num1 = num1 * d + b[i];
        	}
        	return num1;
        }
        
        int main(){
        	int n, d;
        	while(1){
        		cin >> n;
        		if(n < 0)break;
        		cin >> d;
        		if(judge(n)){
        			memset(a, 0, sizeof(a));
        			long long ans = change(a, n, d);
        			if(judge(ans)){
        				printf("Yes\n");
        			}else printf("No\n");
        		}else printf("No\n");
        	}
        	return 0;
        }
        
  • 质因数

    • A 1096:寻找最大长度的连续质因数序列,如果最大长度相同,输出第一个数字最小的序列

      • 思路:

        ①首先说明一下自己一开始思考的时候的思维漏洞,就是只用for循环遍历了一次,导致漏了很多答案,其实应该用双重for循环来做。

        ②正确思路:外层for循环从2遍历到sqrt(n) + 1,内层for循环j从i开始,到maxn,寻找最大连续质因数序列。然后跳出内层for循环,判断此次长度是否是最大长度。

      • 代码实现

        #include<bits/stdc++.h>
        using namespace std;
        long long num, temp;
        int main(){
        	cin >> num;
        	int first = 0, len = 0, maxn = sqrt(num) + 1;
        	for(int i = 2; i <= maxn; i++){
        		int j;
        		temp = 1;
        		//通过不断相乘并且是否能够被num整除来寻找最大连续质因数 
        		for(j = i; j <= maxn; j++){
        			temp *= j;
        			if(num % temp != 0)break;
        		}
        		if(j - i > len){
        			len = j - i;
        			first = i;
        		}
        	}
        	if(first == 0){//说明num是一个质数 
        		cout << 1 << endl << num;
        	}else{//说明num不是一个质数 
        		cout << len << endl;
        		for(int i = 0; i < len; i++){
        			cout << first + i;
        			if(i != len - 1)cout << '*';
        		} 
        	}
        	return 0;
        } 
        
  • 大数运算

    • A 1024:大数相加并判断是否是回文。

      • 思路:

        ①难点在于将大数相加的过程写清楚,因为是while循环需要进行多次相加,所以最好使用模板代码,比较清晰。自己在写的过程中,没有使用模板代码,导致书写错误。

        ②熟悉大数运算的操作过程,此代码还需要更加熟悉。

      • 代码实现

        #include<bits/stdc++.h>
        using namespace std;
        struct bign{
        	int d[1000];
        	int len;
        	bign(){
        		memset(d, 0, sizeof(d));
        		len = 0;
        	}
        };
        bign change(char str[]){
        	bign a;
        	a.len = strlen(str);
        	for(int i = 0; i < a.len; i++){
        		a.d[i] = str[a.len - 1 - i] - '0';
        	}
        	return a;
        }
        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;
        }
        bool judge(bign a){//判断是否是回文 
        	for(int i = 0; i <= a.len / 2; i++){
        		if(a.d[i] != a.d[a.len-1-i]){
        			return false;
        		}
        	}
        	return true;
        }
        void print(bign a){
        	for(int i = a.len - 1; i >= 0; i--){
        		printf("%d", a.d[i]);
        	}
        	printf("\n");
        }
        int main(){
        	char str[100];
        	int t, k = 0;
        	cin >> str >> t;
        	bign a = change(str);//大数使用结构体存储,不容易出错
        	while(k < t && judge(a) == false){
        		bign b = a; //如果是结构体类型大数,就可以直接赋值
        		reverse(b.d, b.d + b.len);
        		a = add(a, b);
        		k++; 
        	} 
        	print(a);
        	printf("%d\n", k);
        	return 0;
        } 
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦想总比行动多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值