PAT之水题:逻辑题、数学问题(素数、多项式、分数、大整数、进制转换)

这篇博客总结了PAT考试中的逻辑题和数学问题,涵盖素数判断、多项式运算、大整数处理、分数运算和进制转换等主题。通过实例分析了数组逻辑、时间序列模拟、图形输出、模拟算法等,同时提供了多项式加法、乘法、大整数加法以及分数加法的代码实现,并讨论了进制转换中的注意事项和错误处理策略。

数学问题总结笔记:进制转换


1 逻辑题

  • 数组+逻辑

1008(20:数组)

(1)题目
电梯(数组)

(2)代码

#include<cstdio>

using namespace std;

const int N=110;

int main(){
    int a[N];
    int n;
    scanf("%d", &n);
    for(int i=1; i<=n; i++){
        scanf("%d", &a[i]);
    }
    int total=0;
    a[0] = 0;
    for(int i=1; i<=n; i++){
        if(a[i] > a[i-1]){
            total = total +  (a[i]-a[i-1])*6;
        }else{
            total = total + (a[i-1]-a[i])*4;
        }
        total += 5;
    }
    printf("%d", total);
    return 0;
}

1017(25:时间序列模拟 + 优先级队列)

(1)题目
时间序列模拟 + 优先级队列,多个窗口排队办业务

(2)代码

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>

using namespace std;

typedef struct Node{
	int come;
	int process;
	int out;
}Node;

vector<Node> vect;
int endTime = 17*3600+1;

bool cmp1( Node no1, Node no2){
	return no1.come < no2.come;
}

struct cmp2{
	bool operator()(const Node &no1, const Node &no2){
		return no1.out > no2.out;
	}
};


int main(){
	//freopen("in.txt", "r",stdin);

	int n, k;
	scanf("%d%d", &n, &k);
	Node node;
	for(int i=0; i<n; i++){
		int hh,mm,ss,p;
		scanf("%d:%d:%d%d", &hh, &mm, &ss, &p);
		int t = hh*3600+mm*60+ss;
		if(t < endTime){
			node.come = t;
			node.process = p*60;
			vect.push_back(node);
		}
	}
	//
	sort(vect.begin(), vect.end(), cmp1);
	priority_queue<Node, vector<Node>, cmp2> pq;
	int wait=0;
	int tempTime=8*3600;
	if(vect[0].come <= tempTime){		//等待
		vect[0].out = tempTime+vect[0].process;
		wait += (tempTime-vect[0].come);
	}else{		//不用等
		vect[0].out = vect[0].come+vect[0].process;
	}
	pq.push(vect[0]);
	int id=1;
	while(!pq.empty() && id<vect.size()){
		if(pq.size()<k){		//未满,进
			if(vect[id].come <= tempTime){		//等待
				vect[id].out = tempTime+vect[id].process;
				wait += (tempTime-vect[id].come);
			}else{	//不用等
				vect[id].out = vect[id].come+vect[id].process;
			}
			pq.push(vect[id]);
			id++;
		}else{		//满了,出
			Node f = pq.top();
			tempTime = f.out;
			pq.pop();
		}
	}
	printf("%.1f", (double)wait/(60*vect.size()));

	//fclose(stdin);
	return 0;
}

(3)小结

  • 以秒为单位,X:Y:Z时间点的秒数为:X*3600+Y*60+Z(以00:00:00为基准)
  • STL:priority_queue
    初始化
priority_queue<int> pq;	//大根堆
priority_queue<int, vector<int>, greater<int> > pq;  //小根堆
priority_queue<Node, vector<Node>, cmp> pq;  

1031(20:数学规律+图形输出)

(1)题目
数学规律+图形输出,字符串U形打印

(2)代码

#include<cstdio>
#include<string>
#include<iostream>

using namespace std;

int main(){
	//freopen("in.txt", "r",stdin);

	string s;
	cin>>s;
	int n = s.length();
	int k = (n+2)/3;
	int n2 = n+2-2*k;
	for(int i=0; i<k-1; i++){
		printf("%c", s[i]);
		for(int j=0; j<n2-2; j++){
			printf(" ");
		}
		printf("%c\n", s[n-i-1]);
	}
	//最下一行
	for(int i=0; i<n2; i++){
		printf("%c", s[i+k-1]);
	}

	//fclose(stdin);
	return 0;
}

(3)小结

  • 数学规律:尽量手写化简,最简(一个表达式)

化简后的正确代码:

int k = (n+2)/3;
int n2 = n+2-2*k;

未化简的错误代码:

int k=-1, n2;
	int max_k = -1;
	for(int i=3; i<=n; i++){
		if((n+2-i)%2==0){
			k = (n+2-i)/2;
		}
		if(k>max_k && k<=i){
			max_k = k;
		}
	}

	k = max_k;
	n2 = n+2-2*k;
  • 图形打印,先存到二维数组里,再printf

1042(20:模拟)

(1)题目
模拟,洗牌

(2)代码

#include<cstdio>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>

using namespace std;

string str[55];
string tempStr[55];

int main(){
	//freopen("in.txt", "r",stdin);

	stringstream ss;
	string s[14];
	for(int i=1; i<=13; i++){
		ss<<i;
		s[i] = ss.str();
		ss.clear();
		ss.str("");
	}
	for(int i=1; i<=13; i++){
		str[i] = "S"+s[i];
		str[i+13] = "H"+s[i];
		str[i+26] = "C"+s[i];
		str[i+39] =  "D"+s[i];
	}
	str[53] = "J1";
	str[54] = "J2";
	for(int i=1; i<=54; i++){
		tempStr[i] = str[i];
	}
	int n;
	scanf("%d", &n);
	int arr[55];
	for(int i=1; i<=54; i++){
		scanf("%d", &arr[i]);
	}
	for(int i=0; i<n; i++){
		for(int j=1; j<=54; j++){
			int id = arr[j];
			str[id] = tempStr[j];
		}
		for(int i=1; i<=54; i++){
			tempStr[i] = str[i];
		}
	}
	for(int i=1; i<=54; i++){
		if(i!=1) printf(" ");
		printf("%s", str[i].c_str());
	}

	//fclose(stdin);
	return 0;
}

(3)小结

  • stringstream ss,多次使用 清空操作:
ss.str("");
ss.clear();
  • 看清题目,不是交换a和b
    当例子输出的答案错误,一定要手动模拟例子,看是否理解了题目意思
  • 最后直接输出int和string的对应关系,不用存string
    char c[6] = {"SHCDJ"};
    for(int i = 1; i < 55; i++) {
        end[i] = end[i] - 1;
        printf("%c%d", c[end[i]/13], end[i]%13+1);
        if(i != 54) printf(" ");
    }

1046(20:模拟 + 超时(设置辅助数组))

(1)题目
模拟 + 超时(设置辅助数组),环上两点最短距离

(2)代码

#include<cstdio>
#include<algorithm>

using namespace std;

const int N = 100000+10;

int arr[N];
int dist[N];	//dist[i]为1到i+1的距离和

int main(){
	//freopen("in.txt", "r",stdin);

	int n;
	scanf("%d", &n);
	int sum=0;
	dist[0] = 0;
	for(int i=1; i<=n; i++){
		scanf("%d", &arr[i]);
		sum += arr[i];
		dist[i] = sum;
	}
	int m;
	scanf("%d", &m);
	for(int i=0; i<m; i++){
		int a,b;
		scanf("%d%d", &a, &b);
		int c,d;
		c = min(a,b);
		d = max(a,b);
		//
		printf("%d\n", min(dist[d-1]-dist[c-1], sum-(dist[d-1]-dist[c-1])));
	}

	//fclose(stdin);
	return 0;
}

(3)小结

  • 以下超时,外层必须为10^4,故里层必须为O(1)
for(int i=0; i<m; i++){  //10^4
	int a,b;
	scanf("%d%d", &a, &b);
	int c,d;
	c = min(a,b);
	d = max(a,b);
	int dist=0;
	for(int j=c;j<d;j++){	//10^5
		dist += arr[j];
	}
	printf("%d\n", min(dist, sum-dist));
}

新设一个辅助数组,用空间换时间

int dist[N];	//dist[i]为1到i+1的距离和

1065(20:64位加法判断溢出(A+B 大于或小于 C))

(1)题目
64位加法判断溢出(A+B 大于或小于 C)

(2)代码

#include<cstdio>

using namespace std;

int main(){
	//freopen("in.txt", "r",stdin);

	int n;
	scanf("%d", &n);
	long long a,b,c,sum;
	for(int i=1; i<=n; i++){
		scanf("%lld%lld%lld", &a, &b, &c);
		sum = a+b;
		//
		if(a>0 && b>0 && sum<0){
			printf("Case #%d: true\n", i);
		}else if(a<0 && b<0 && sum>=0){
			printf("Case #%d: false\n", i);
		}else if(sum>c){
			printf("Case #%d: true\n", i);
		}else{
			printf("Case #%d: false\n", i);
		}
	}

	//fclose(stdin);
	return 0;
}

(3)小结

  • 此题不需要求A+B=?,只需判断A+B 大于或小于 C,因此不是大整数题
  • 关于longlong溢出问题
long long a, b, c;
long long sum=a+b;

//以下溢出【说明sum极小或极大】
a>0 && b>0 && sum<0		// sum极大,但c在longlong范围,因此 sum >> c
a<0 && b<0 && sum>=0	// sum极小,但c在longlong范围,因此 sum << c
//其它情况没有溢出,可正常比较sum 和 c

1105(25:模拟,数组)【非满分】

(1)题目

模拟,数组,螺旋矩阵

(2)代码

#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<functional>

using namespace std;

const int INF=0x3f3f3f3f;

vector<int> vect;


int main(){
	//freopen("in.txt", "r",stdin);

	int N;
	scanf("%d", &N);
	vect.resize(N);
	for(int i=0; i<N; i++){
		scanf("%d", &vect[i]);
	}
	int n,m;
	for(n=(int)sqrt((double)N); n>=1; n--){
		if(N%n==0){
			m = N/n;
			break;
		}
	}
	sort(vect.begin(), vect.end(), greater<int>());
	//
	vector<vector<int> > arr(m, vector<int>(n,INF));
	int cnt=0;
	int row=0, coun=n-1;
	while(cnt!=N){
		int flag=0;
		for(int i=0; i<n; i++){
			if(cnt==N){
				flag=1;
				break;
			}
			if(arr[row][i]==INF){
				arr[row][i] = vect[cnt];
				cnt++;
			}			
		}
		if(flag==1) break;
		for(int i=0; i<m; i++){
			if(cnt==N){
				flag=1;
				break;
			}
			if(arr[i][coun]==INF){
				arr[i][coun] = vect[cnt];
				cnt++;
			}			
		}
		if(flag==1) break;
		for(int i=n-1; i>=0; i--){
			if(cnt==N){
				flag=1;
				break;
			}
			if(arr[row+m-1][i]==INF){
				arr[row+m-1][i] = vect[cnt];
				cnt++;
			}
		}
		if(flag==1) break;
		for(int i=m-1; i>=0; i--){
			if(cnt==N){
				flag=1;
				break;
			}
			if(arr[i][coun-n+1]==INF){
				arr[i][coun-n+1] = vect[cnt];
				cnt++;
			}	
		}
		if(flag==1) break;
		row++;
		coun--;
	}
	for(int i=0; i<m; i++){
		for(int j=0; j<n; j++){
			if(j!=0) printf(" ");
			printf("%d", arr[i][j]);
		}
		printf("\n");
	}

	//fclose(stdin);
	return 0;
}

(3)小结

  • vector二维:arr[m][n]
vector<vector<int> > arr(m, vector<int>(n, INF));

1109(25:模拟,数组)【非满分】

(1)题目
模拟,数组,照相队形

(2)代码

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>

using namespace std;

typedef struct Node{
	string name;
	int height;
}Node;

vector<Node> vect;

bool cmp(Node no1, Node no2){
	if(no1.height== no2.height){
		return no1.name < no2.name;
	}else{
		return no1.height < no2.height;
	}
}

bool cmp2(Node no1, Node no2){
	if(no1.height == no2.height){
		return no1.name < no2.name;
	}else{
		return no1.height > no2.height;
	}
}



int main(){
	//freopen("in.txt", "r",stdin);

	int n,k;
	scanf("%d%d", &n, &k);
	Node node;
	for(int i=0; i<n; i++){
		string name;
		cin>>name;
		int h;
		scanf("%d", &h);
		node.name = name;
		node.height = h;
		vect.push_back(node);
	}
	sort(vect.begin(), vect.end(), cmp);
	int r_num = n/k;
	int r_last_num = r_num + n%k;
	vector<vector<Node> > group(k); 
	vector<Node> groupSub,temp;
	int cnt=0;
	int start, mid;		//开始、中间、最后的序号
	for(int i=0; i<k; i++){
		if(i!=k-1){
			for(int i=cnt; i<cnt+r_num; i++){
				groupSub.push_back(vect[i]);
			}
			sort(groupSub.begin(), groupSub.end(), cmp2);
			temp.resize(r_num);
			start = 0;		//groupSub[start],此行中最高
			mid = r_num/2;
			for(int i=0; i<=r_num/2; i++){
				if(i==0){ 
					temp[mid] = groupSub[start];
					cnt++;
					start++;
					continue;					
				}
				if(start==r_num) break;
				temp[mid-i] = groupSub[start];
				cnt++;
				start++;
				if(cnt==r_num) break;
				temp[mid+1] = groupSub[start];
				cnt++;
				start++;
			}
			group[i] = temp;
			temp.clear();
			groupSub.clear();
		}else{
			for(int i=cnt; i<cnt+r_last_num; i++){
				groupSub.push_back(vect[i]);
			}
			sort(groupSub.begin(), groupSub.end(), cmp2);
			temp.resize(r_last_num);
			start = 0;		//vect[start],此行中最高
			mid = r_last_num/2;
			int cnt=0;
			for(int i=0; i<=r_last_num/2; i++){
				if(i==0){ 
					temp[mid] = groupSub[start];
					cnt++;
					start++;
					continue;					
				}
				if(cnt==r_last_num) break;
				temp[mid-i] = groupSub[start];
				cnt++;
				start++;
				if(cnt==r_last_num) break;
				temp[mid+1] = groupSub[start];
				cnt++;
				start++;
			}
			group[i] = temp;
			temp.clear();
			groupSub.clear();
		}
	}
	for(int i=k-1; i>=0; i--){
		for(int j=0; j<group[i].size(); j++){
			if(j!=0) printf(" ");
			printf("%s",group[i][j].name.c_str());
		}
		printf("\n");
	}


	//fclose(stdin);
	return 0;
}

1117(25:逻辑)

(1)题目
E:在n天中有E天,每天的英里都>E,求最大E

(2)代码

#include<cstdio>
#include<algorithm>
#include<functional>

using namespace std;

const int N=100000 + 10;

int main(){
    int a[N];
    int n;
    scanf("%d", &n);
    for(int i=1; i<=n; i++){
        scanf("%d", &a[i]);
    }
    sort(a+1, a+n+1, greater<int>());
    int max_E=0;
    int end_i = 0;		// break最外层循环标志
    for(int i=n; i>=1; i--){        // 有i天
        if(end_i){
            break;
        }
        for(int j=1; j<=n; j++){
            if(j==i && a[j]>i){
                max_E = i;
                end_i = 1;
                break;
            }
            if(a[j] > i) continue;  // 保证前a[1]~a[j-1]都>i
            else break;
        }
    }
    printf("%d", max_E);

    return 0;
}

(3)小结

  • 评判结果:出现答案错误
    一:【错误少】特例 没考虑到(边界)
    二:【错误一半】分支代码写错,因为所给特例 并未测试到分支情况
    解决:改写特例,测试分支
    三:【错误大多】算法错误

1128(20:模拟,数组)

(1)题目
模拟,数组,Q皇后

(2)代码

#include<cstdio>
#include<algorithm>

using namespace std;

const int N=1000 + 10;

int Q[N];

int main(){
    int k;
    scanf("%d", &k);
    for(int i=0; i<k; i++){
        int n;
        scanf("%d", &n);
        int fail=0;
        for(int j=1; j<=n; j++){
            scanf("%d", &Q[j]);
            // 对于Q[1]~ Q[j-1],和Q[j]操作
            if(!fail){
                for(int t=1; t<j; t++){
                    if(Q[t] == Q[j] || abs(Q[t]-Q[j])==abs(t-j)){
                        //在同一行 || 在同一对角线(左上-->右下)
                        fail=1;
                        break;
                    }
                }
            }
        }
        if(!fail){
            printf("YES\n");
        }else{
            printf("NO\n");
        }
    }

    return 0;
}


(3)小结

  • n个数需要判别有无重复:
    另设置一个数组:a[i] = 1 or 0(1代表 数i 已存在)
  • 同一对角线
    a[ i1 ][ j1 ] 和 a[ i2 ][ j2 ] :
    (1)在同一对角线上(左上–>右下): 行-行 = 列-列
    abs(i2 - i1) == abs(j2 - j1)
    (2)在同一对角线上(左下–>右上):行+列 = 行+列
    i1+j1 = i2 + j2

2 数学问题

2.1 素数

模板

  • 0和1不是素数,也不是合数
  • 素数:x>1且为整数,只能被1和自身整除

(1)判断n是不是素数

bool isPrime(int n){
	if(n<=1)  return false;
	for(int i=2; i<=(int)sqrt((double)n); i++){	//i:2 到 sqrt(n)
		if(n%i==0){
			return false;
		}
	}
	return true;
}

(2)素数表

const int N=500000;
bool prime[N];		//素数表:prime[i]=true,i为素数
fill(prime, prime+N, true);
for(int i=2; i*i<N; i++){
	for(int j=2; j*i<N; j++){
		prime[i*j] = false;			//i的所有倍数都不是素数
	}
}

1015(20:判断素数 + 进制转换)

(1)题目
判断素数 + 进制转换

(2)代码

#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>

using namespace std;


bool isPrime(int n){
	if(n<=1)  return false;
	for(int i=2; i<=(int)sqrt((double)n); i++){	//i:2 到 sqrt(n)
		if(n%i==0){
			return false;
		}
	}
	return true;
}


int main(){
	//freopen("in.txt", "r",stdin);
	
	int n;
	while(scanf("%d", &n)){
		if(n<0) break;
		int d;
		scanf("%d", &d);		
		if(isPrime(n)){
			// 十进制转为d进制
			vector<int> vect;
			int t=n;
			while(t!=0){
				vect.push_back(t%d);
				t = t/d;
			}
			//将vect逆转
			reverse(vect.begin(), vect.end());
			//将d进制转为十进制
			t=0;
			for(int i=vect.size()-1; i>=0; i--){
				t = t*d + vect[i];
			}
			if(isPrime(t)){
				printf("Yes\n");
			}else{
				printf("No\n");
			}
		}else{
			printf("No\n");
		}		
	}
	

	//fclose(stdin);
	return 0;
}

(3)小结

  • radix D:D进制
  • 进制转换
// 10进制转为d进制:n转为arr
vector<int> vect;	//arr[0]为低位
int t=n;
while(t!=0){
	vect.push_back(t%d);
    t = t/d;
}
// d进制转为10进制:vect转为n
n=0;
for(int i=vect.size()-1; i>=0; i--){	//从d进制高位开始
	n = n*d + vect[i];
}
  • 逆转函数 reverse
#include<algorithm>
reverse(string.begin(), string.end());
  • 一直输入
int n;
while(scanf("%d", &n)){
	if(n<0) break;
	...
}

1116(20:判断素数 + hash数字存储)

(1)题目

判断素数 + hash数字存储

(2)代码

#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>

using namespace std;

const int N=10000+10;


int visit[N];
vector<int> vect[N];

bool isPrime(int n){
	if(n<=1)  return false;
	for(int i=2; i<=(int)sqrt((double)n); i++){	//i:2 到 sqrt(n)
		if(n%i==0){
			return false;
		}
	}
	return true;
}


int main(){
	//freopen("in.txt", "r",stdin);
	
	fill(visit, visit+N, 0);
	int n;
	scanf("%d", &n);
	int champ_id = 0;
	for(int i=1; i<=n; i++){
		int t;
		scanf("%d", &t);
		if(i==1) champ_id=t;
		vect[t].push_back(i);
		visit[t]++;
	}
	int k;
	scanf("%d", &k);
	for(int i=0; i<k; i++){
		int id;
		scanf("%d",&id);
		if(visit[id]==2){
			printf("%04d: Checked\n", id);
		}else if(visit[id]==0){
			printf("%04d: Are you kidding?\n", id);
		}else{
			if(id==champ_id){
				printf("%04d: Mystery Award\n", id);				
			}
			else if(isPrime(vect[id][0])){
				printf("%04d: Minion\n", id);			
			}else{
				printf("%04d: Chocolate\n", id);			
			}
			visit[id]++;
		}
	}
	

	//fclose(stdin);
	return 0;
}

1059(25:素数表 + 因式分解)

(1)题目
素数表 + 因式分解

(2)代码

#include<cstdio>
#include<algorithm>
#include<set>

using namespace std;

const int N=500000;

bool prime[N];		//素数表:=true,为素数


int main(){
	//freopen("in.txt", "r",stdin);

	fill(prime, prime+N, true);
	for(int i=2; i*i<N; i++){
		for(int j=2; j*i<N; j++){
			prime[i*j] = false;			//i的所有倍数都不是素数
		}
	}
	//
	long long n;
	scanf("%lld", &n);
	printf("%lld=", n);
	if(n==1){
		printf("1");
	}
	int i=2;
	int flag=0;
	while(n>=2){
		int cnt=0;
		while(prime[i]==true && n%i==0){
			cnt++;
			n = n/i;
		}
		if(cnt==1){
			if(flag==0){
				printf("%d", i);
				flag=1;
			}else{
				printf("*%d", i);				
			}	
		}else if(cnt!=0){
			if(flag==0){
				printf("%d^%d", i, cnt);
				flag=1;
			}else{
				printf("*%d^%d", i, cnt);	
			}	
		}
		i++;
	}
	
	//fclose(stdin);
	return 0;
}

2.2 多项式

1002(25:多项式加法)

(1)题目

两个多项式的加法

(2)代码

#include<cstdio>
#include<algorithm>
#include<set>

using namespace std;

const int N=1000+10;

double A[N];

int main(){
	//freopen("in.txt", "r",stdin);
	
	fill(A, A+N, 0);
	for(int i=0; i<2; i++){
		int n;
		scanf("%d", &n);
		for(int j=0; j<n; j++){
			int e;
			double c;
			scanf("%d%lf", &e, &c);
			A[e] += c;
		}
	}
	int cnt=0;
	for(int i=N-1; i>=0; i--){
		if(A[i]!=0.0){
			cnt++;
		}
	}
	printf("%d", cnt);
	for(int i=N-1; i>=0; i--){
		if(A[i]!=0.0){
			printf(" %d %.1f", i, A[i]);
		}
	}
	

	//fclose(stdin);
	return 0;
}

(3)小结

  • 多项式的数组大小 = 指数的最大值
    A和B的指数最大值为 maxA, maxB
    加法:A+B的指数最大值:max{maxA, maxB}
    乘法:A*B的指数最大值:maxA +maxB

1009(25:多项式乘法)

(1)题目
两个多项式的乘法

(2)代码

#include<cstdio>
#include<algorithm>
#include<set>

using namespace std;

const int N=1001;

double A[N],B[N*2];

int main(){
	//freopen("in.txt", "r",stdin);
	
	fill(A, A+N, 0);
	fill(B, B+2*N, 0);
	int n;
	scanf("%d", &n);
	for(int j=0; j<n; j++){
		int e;
		double c;
		scanf("%d%lf", &e, &c);
		A[e] = c;
	}
	//第二个多项式
	scanf("%d", &n);
	for(int j=0; j<n; j++){
		int e;
		double c;
		scanf("%d%lf", &e, &c);
		for(int i=0; i<N; i++){
			if(A[i]!=0.0){
				B[e+i] += c*A[i];
			}
		}
	}
	int cnt=0;
	for(int i=2*N-1; i>=0; i--){
		if(B[i]!=0.0){
			cnt++;
		}
	}
	printf("%d", cnt);
	for(int i=2*N-1; i>=0; i--){
		if(B[i]!=0.0){
			printf(" %d %.1f", i, B[i]);
		}
	}
	

	//fclose(stdin);
	return 0;
}

(3)小结

  • 多个答案错误:当A和B的最大指数为1000,乘积的最大指数为2000
    在这里插入图片描述

2.3 大整数

1023(20:大整数加法)

(1)题目

两个大整数相加

(2)代码

#include<cstdio>
#include<sstream>
#include<string>
#include<iostream>
#include<vector>

using namespace std;


int main(){
	//freopen("in.txt", "r",stdin);

	string s;
	cin>>s;
	vector<int> v;
	int visit1[10] = {0};
	int visit2[10] = {0};
	for(int i=0; i<s.length(); i++){
		int a = s[i]-'0';
		v.push_back(a);
		visit1[a]++;
	}
	vector<int> doub;
	int c=0;
	for(int i=v.size()-1; i>=0; i--){
		int a = c + v[i]*2;
		c = a/10;
		doub.push_back(a%10);
	}
	if(c!=0){
		doub.push_back(c);
	}
	for(int i=0; i<doub.size(); i++){
		visit2[doub[i]]++;
	}
	int flag=0;
	for(int i=0; i<10; i++){
		if(visit1[i]!=visit2[i]){
			flag=1;
			break;
		}
	}
	if(flag==0){
		printf("Yes\n");	//v={0}
	}else{
		printf("No\n");
	}
	for(int i=doub.size()-1; i>=0; i--){
		printf("%d", doub[i]);
	}

	//fclose(stdin);
	return 0;
}

2.5 分数四则运算

模板

(1)最大公约数、最小公倍数

// 最大公约数
int gcd(int a, int b){		
	if(b==0){
		return a;
	}
	return gcd(b, a%b);
}
// 最小公倍数
int lcm(int a, int b){			
	int c = gcd(a,b);
	//return a*b/c;
	return a/c*b;
}

(2)分数
始终让:
符号总在分子上,分母为非负
四则运算过程中(分数有符号)

typedef struct Node{
	long long up;		//分子
	long long down;		//分母
}Node;


// 加减乘除:up有符号
Node sum(Node no1, Node no2){
	Node node;
	node.down = no1.down * no2.down;
	node.up = no1.up * no2.down + no2.up * no1.down;
	return node;
}
Node diff(Node no1, Node no2){
	Node node;
	node.down = no1.down * no2.down;
	node.up = no1.up * no2.down - no2.up * no1.down;
	return node;
}
Node prod(Node no1, Node no2){
	Node node;
	node.down = no1.down * no2.down;
	node.up = no1.up * no2.up;
	return node;
}
Node quo(Node no1, Node no2){
	Node node;
	node.down = no1.down * no2.up;
	node.up = no1.up * no2.down;
	return node;
}


// 化简约分
long long gcb(long long a, long long b){
	if(b==0) return a;
	gcb(b, a%b);
}
Node simple(Node node){	// -10 / -5	
	if(node.down==0){
		return node;
	}
	if(node.up==0){
		node.down = 1;
		return node;
	}
	if(node.down<0){		//将负号维持在分子
		node.up = -node.up;
		node.down = -node.down;
	}
	// 分子/分母约分
	long long g = gcb(abs(node.up), node.down);
	node.up /= g;
	node.down /= g;
	return node;
}

// 输出
void out(Node node){
	if(node.down==0){		
		printf("Inf");
		return;
	}
	if(node.up==0){
		printf("0");
		return;
	}
	if(node.up<0) printf("(");
	if(node.down==1){
		printf("%lld", node.up);
	}else if(abs(node.up)>node.down){
		printf("%lld ", (node.up/node.down));
		printf("%lld/%lld",abs(node.up%node.down), node.down);	
	}else{
		printf("%lld/%lld", node.up, node.down);
	}
	if(node.up<0) printf(")");
}

1081(20:分数的加法)

(1)题目
多个分数累加

(2)代码

#include<cstdio>
#include<vector>

using namespace std;


typedef struct Node{
	long long numera;
	long long denom;
}Node;

vector<Node> fra;

Node sumFra(Node no1, Node no2){
	Node node;
	node.denom = no1.denom * no2.denom;
	node.numera = no1.numera * no2.denom + no2.numera * no1.denom;
	return node;
}

long long gcb(long long a, long long b){
	if(b==0) return a;
	gcb(b, a%b);
}
	
int main(){
	//freopen("in.txt", "r",stdin);

	int n;
	scanf("%d", &n);
	Node node;
	for(int i=0;i<n; i++){
		long long a,b;
		scanf("%lld/%lld",&a, &b);
		node.numera = a;
		node.denom = b;
		fra.push_back(node);
	}
	//  求和
	node.numera = 0;
	node.denom = 1;
	long long state=1;
	for(int i=0; i<fra.size(); i++){
		node = sumFra(node, fra[i]);
		// 约分
		if( node.numera<0){
			node.numera *= (-1);
			state=-1;
		}
		long long g = gcb(node.numera, node.denom);
		node.numera /= g;
		node.denom /= g;
	}	
	//
	if(node.numera==0) printf("%lld", 0);
	else{
		long long inte_p = node.numera / node.denom;
		if(inte_p == 0){
			printf("%lld/%lld", node.numera*state, node.denom);
		}else{
			if(node.denom==1){
				printf("%lld", inte_p*state);
			}else{
				printf("%lld %lld/%lld", inte_p*state, node.numera%node.denom, node.denom);
			}			
		}
	}

	//fclose(stdin);
	return 0;
}

(3)小结

  • 浮点错误: /0 或 %0 或 超出int/long long 范围
    此题累加时,超出long long 范围
  • 运算一次,化简一次,不要等到最后一次性化简

1088(20:分数的四则运算)

(1)题目
分数的四则运算

(2)代码

#include<cstdio>
#include<algorithm>

using namespace std;

typedef struct Node{
	long long up;
	long long down;
}Node;


// 加减乘除:up有符号
Node sum(Node no1, Node no2){
	Node node;
	node.down = no1.down * no2.down;
	node.up = no1.up * no2.down + no2.up * no1.down;
	return node;
}

Node diff(Node no1, Node no2){
	Node node;
	node.down = no1.down * no2.down;
	node.up = no1.up * no2.down - no2.up * no1.down;
	return node;
}

Node prod(Node no1, Node no2){
	Node node;
	node.down = no1.down * no2.down;
	node.up = no1.up * no2.up;
	return node;
}

Node quo(Node no1, Node no2){
	Node node;
	node.down = no1.down * no2.up;
	node.up = no1.up * no2.down;
	return node;
}



long long gcb(long long a, long long b){
	if(b==0) return a;
	gcb(b, a%b);
}


Node simple(Node node){		
	if(node.down==0){
		return node;
	}
	if(node.up==0){
		node.down = 1;
		return node;
	}
	if(node.down<0){		//将负号维持在分子
		node.up = -node.up;
		node.down = -node.down;
	}
	// 分子/分母约分
	long long g = gcb(abs(node.up), node.down);
	node.up /= g;
	node.down /= g;
	return node;
}

void out(Node node){
	if(node.down==0){		
		printf("Inf");
		return;
	}
	if(node.up==0){
		printf("0");
		return;
	}
	if(node.up<0) printf("(");
	if(node.down==1){
		printf("%lld", node.up);
	}else if(abs(node.up)>node.down){
		printf("%lld ", (node.up/node.down));
		printf("%lld/%lld",abs(node.up%node.down), node.down);	
	}else{
		printf("%lld/%lld", node.up, node.down);
	}
	if(node.up<0) printf(")");
}

int main(){
	freopen("in.txt", "r", stdin);

	Node node[2];
	for(int i=0; i<2; i++){
		long long a,b;
		scanf("%lld/%lld", &a, &b);
		node[i].up = a; 
		node[i].down = b;
	}
	Node result[4];
	result[0] = sum(node[0], node[1]);
	result[1] = diff(node[0], node[1]);
	result[2] =  prod(node[0], node[1]);
	result[3] =  quo(node[0], node[1]);
	for(int i=0; i<2; i++){
		node[i] = simple(node[i]);
	}
	for(int i=0; i<4; i++){
		result[i] = simple(result[i]);
	}
	// sum
	out(node[0]);
	printf(" + ");
	out(node[1]);
	printf(" = ");
	out(result[0]);
	printf("\n");	
	// diff
	out(node[0]);
	printf(" - ");
	out(node[1]);
	printf(" = ");
	out(result[1]);
	printf("\n");	
	// prod
	out(node[0]);
	printf(" * ");
	out(node[1]);
	printf(" = ");
	out(result[2]);
	printf("\n");	
	// quo
	out(node[0]);
	printf(" / ");
	out(node[1]);
	printf(" = ");
	out(result[3]);
	printf("\n");	

	fclose(stdin);
	return 0;
}

2.6 进制转换

模板

// 10进制转为d进制:n转为arr
vector<int> vect;
void toD(int n, int d){
	int t=n;
	while(t!=0){
		vect.push_back(t%d);		//低位先进
		t = t/d;
	}
}

// d进制转为10进制:vect转为n
int toTen(int d){
	int n=0;
	for(int i=vect.size()-1; i>=0; i--){	//从高位开始
		n = n*d + vect[i];
	}
}

1027(20:10进制转为13进制)

(1)题目
10进制转为13进制

(2)代码

#include<cstdio>
#include<string>

using namespace std;


string base[13] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C"};

int main(){
	//freopen("in.txt","r",stdin);

	int n;
	printf("#");
	for(int i=0; i<3; i++){
		scanf("%d", &n);
		printf("%s%s", base[n/13].c_str(), base[n%13].c_str());
	}

	//fclose(stdin);
	return 0;
}

(3)小结

  • 0<= n <=168 转为13进制(最多2位:168 = 13*12+12 = CC):
    a[0] = n /13
    a[1] = n%13

1058(20:10进制每位的任意进制 互相转换)

(1)题目
10进制 每位的任意进制 互相转换

(2)代码

#include<cstdio>

using namespace std;

long long a[3];
long long b[3];

long long to_ten(long long arr[]){	//用long long,防溢出
	long long n = arr[2] + arr[1]*29 + arr[0]*29*17;
	return n;
}

int main(){
	//freopen("in.txt","r",stdin);

	scanf("%lld.%lld.%lld", &a[0], &a[1], &a[2]);
	scanf("%lld.%lld.%lld", &b[0], &b[1], &b[2]);
	// 转换为10进制
	long long sum = to_ten(a) + to_ten(b);
	//
	printf("%lld.%lld.%lld\n", sum/(29*17), (sum%(29*17))/29, (sum%(29*17))%29);	

	//fclose(stdin);
	return 0;
}

(3)小结

  • 一个数范围 [0~x],则为(x+1)进制
    3位数(a[0]最高), a[0]; a[1]:[0 ~ p1),p1进制; a[2]:[0~p2),p2进制
    转换为10进制: n = a[2] + a[1] * p2 + a[0] * p2 * p1
    即 a[i] * 前面所有进制的乘积(累乘)
  • 如果代码出现 long long,那么最好所有整数都有long long(包括数组、STL存储等)
    不要int和long long转换,会损失,出现答案错误

1100(20:10进制 13进制 相互转换)

(1)题目
10进制 13进制 相互转换

(2)代码

#include<cstdio>
#include<string>
#include<iostream>
#include<cctype>

using namespace std;

string low[13] = {"tret", "jan", "feb", "mar", "apr", "may", "jun", "jly", "aug", "sep", "oct", "nov", "dec"};
string high[13] = {"", "tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mer", "jou"};  // high[0]不用


string strs[2];		//168(10进制)转为13进制,不超过2位
int LEN;	//实际位数


void to_p(int n){
	//倒存
	strs[1] = low[n%13];
	strs[0] = high[n/13];
}

int index(string ss[], string &s){
	for(int i=0; i<13;  i++){
		if(ss[i]==s){
			return i;
		}
	}
	return -1;
}
int to_ten(){
	int loc;
	if(LEN==1){
		loc = index(low,strs[0]);
		if(loc!=-1){
			return loc;		// 如may
		}else{
			loc = index(high,strs[0]);
			return loc*13;	//如tam
		}
	}else{
		int n=0;
		n += index(low, strs[1]);
		n += index(high, strs[0])*13;
		return n;
	}
}

// 一行string,根据空格切分成strs[]
void fun(string &s){
	char ch;
	string word="";
	int k=0;
	for(int i=0; i<s.length(); i++){
		ch = s[i];
		if(ch==' '){
			strs[k] = word;
			word = "";
			k++;
		}else{
			word += ch;
			if(i==s.length()-1){
				strs[k] = word;
				k++;
			}
		}
	}
	LEN = k;
}

int main(){
	//freopen("in.txt","r",stdin);

	int n;
	scanf("%d", &n);
	cin.ignore();
	for(int i=0; i<n; i++){
		string s;
		getline(cin, s);
		if(isalpha(s[0])){	//13进制转10进制
			fun(s);
			printf("%d\n", to_ten());
		}else{
			int n = stoi(s);
			to_p(n);
			if(strs[0]==""){	//如{"", "may"}
				printf("%s\n", strs[1].c_str());
			}else if(strs[1]=="tret"){		//如{"tam", "tret"}
				printf("%s\n", strs[0].c_str());
			}else{
				printf("%s %s\n", strs[0].c_str(), strs[1].c_str());
			}
		}
	}


	//fclose(stdin);
	return 0;
}

(3)小结

  • string 转为 int、double
    int n = stoi(string);
    double d = stod(string);

  • 一行string,根据 空格 切分成string数组

string strs[100];
int LEN;	//实际strs的个数

// 一行string,根据空格切分成strs[]
void fun(string &s){
	char ch;
	string word="";
	int k=0;
	for(int i=0; i<s.length(); i++){
		ch = s[i];
		if(ch==' '){
			strs[k] = word;
			k++;
			word = "";
		}else{
			word += ch;
			if(i==s.length()-1){		// !!!易漏
				strs[k] = word;
				k++;
			}
		}
	}
	LEN = k;
}

1010(20:36进制内,已知n1的进制,查找n2的进制使10进制下n1==n2)

(1)题目
36进制内,已知n1的进制,查找n2的进制使10进制下n1==n2

(2)代码

#include<cstdio>
#include<vector>
#include<string>
#include<iostream>
#include<map>

using namespace std;


char base[36] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};

int find_base(char x){
	for(int i=0; i<36; i++){
		if(x==base[i]) return i;
	}
	return -1;
}


vector<int> vect;

long long toTen(int d){
	long long n=0;
	for(int i=0; i<vect.size(); i++){
		n = n*d + vect[i];
	}
	return n;
}

int vect_max(){
	int max_v = -1;
	for(int i=0; i<vect.size(); i++){
		if(vect[i]>max_v){
			max_v = vect[i];
		}
	}
	return max_v;
}

	
int main(){
	//freopen("in.txt", "r",stdin);

	int n,m;
	string s1,s2;
	cin>>s1;
	cin>>s2;
	int tax,d;
	scanf("%d%d", &tax, &d);
	if(tax==1){
		//将s1的d进制转换为10进制
		for(int i=0; i<s1.length(); i++){
			vect.push_back(find_base(s1[i]));		//vect[0]为高位
		}
		long long n1 = toTen(d);
		//
		vect.clear();
		for(int i=0; i<s2.length(); i++){
			vect.push_back(find_base(s2[i]));		//vect[0]为高位
		}
		int d2 = vect_max();
		int flag=0;
		for(int i=d2+1; i<36; i++){
			long long n2 = toTen(i);
			if(n1==n2){
				printf("%d", i);
				flag=1;
				break;
			}
		}
		if(flag==0){
			printf("Impossible");
		}
	}else{
		//将s2的d进制转换为10进制
		for(int i=0; i<s2.length(); i++){
			vect.push_back(find_base(s2[i]));		//vect[0]为高位
		}
		long long n2 = toTen(d);
		//
		vect.clear();
		for(int i=0; i<s1.length(); i++){
			vect.push_back(find_base(s1[i]));		//vect[0]为高位
		}
		int d2 = vect_max();
		int flag=0;
		for(int i=d2+1; i<36; i++){
			long long n1 = toTen(i);
			if(n1==n2){
				printf("%d", i);
				flag=1;
				break;
			}
		}
		if(flag==0){
			printf("Impossible");
		}
	}


	//fclose(stdin);
	return 0;
}

(3)小结

  • 进制转换:d进制转为10进制,可能会溢出,用long long
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值