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

被折叠的 条评论
为什么被折叠?



