[机试]第六章 数学问题

part 1 进制转换

例题6.1 二进制数(有空再看看)

KY187 二进制数

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <cstdio>
#include <stack>

using namespace std;


int main() {
    
    
	unsigned int n;
	stack<int> binary;
	
	while (cin >> n) {
    
    
		int index = 0;
		while (n != 0) {
    
    
			binary.push(n % 2);
			n /= 2;
		}
		
		while (!binary.empty()) {
    
    
			printf("%d", binary.top());
			binary.pop();
		}
		printf("\n");
	}



	return 0;
}
  • 进制转换。进制的组成:d_i为数位的值,10为基数,10的各次幂为位权,x为最终的值
    在这里插入图片描述
  • x%基数,得到最低数位的值
    在这里插入图片描述
  • x/基数,高位数值向低位移动。依次求被移动到最低位的值
    在这里插入图片描述

== 这道题用字符串存数位,转换再反转做,int转char总是报错~有没有大佬看到了评论区讲解一下? ==
大概是:str[index++] = (n % 2) + ‘0’; 不知道哪里错了ovo

  • unsigned int 范围(0 ~ 2 32 2^{32} 232 - 1),int/signed int (- 2 31 2^{31} 231 ~ 2 31 2^{31} 231 - 1)。 2 32 2^{32} 232 - 1 = 4294967295(九位)
  • 整数+'0’隐形转化为char类型(int a = 1;char c = a + ‘0’ = ‘1’ 字符转为ascii码的值相加再转化),字符-'0’隐性转化位int类型(char a = ‘1’; int c = a - ‘0’ = 1 字符相减结果为ASCII码值相减)。

在这里插入图片描述

例题6.2 进制转换

KY30 进制转换

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <cstdio>
#include <string>
#include <stack>

using namespace std;

string Divide(string str, int num) {
    
    
	int remainder = 0;
	for (int i = 0; i < str.size(); i++) {
    
    
		int current = remainder * 10 + str[i] - '0';
		str[i] = current / num + '0';
		remainder = current % num;
	}
	int pos = 0;
	while (str[pos] == '0') {
    
    
		pos++;
	}
	return str.substr(pos);
}

int main() {
    
    
	string str;
	while (cin >> str) {
    
    
		stack<int> result;
		while (str.size() != 0) {
    
    
			int last = str[str.size() - 1] - '0';
			result.push(last % 2);
			str = Divide(str, 2);
		}
		while (!result.empty()) {
    
    
			printf("%d", result.top());
			result.pop();
		}
		printf("\n");
	}
	return 0;
}
  • 对数字最低数位取模等效于对于数字取模
  • 字符串除法(模拟除法过程):从高位到低位逐位除以除数,不能整除时保留余数,余数*10和低一位一起处理,但是要处理前置多余的0噢~ovo

例题6.3 十进制与二进制

KY26 10进制 VS 2进制

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <cstdio>
#include <vector>
#include <string>

using namespace std; 

string Divide(string str, int num) {
    
    
	int remainder = 0;
	for (int i = 0; i < str.size(); ++i) {
    
    
		int current = remainder * 10 + str[i] - '0';
		str[i] = current / num + '0';
		remainder = current % num;
	}
	int pos = 0;
	while (str[pos] == '0') {
    
    
		pos++;
	}
	return str.substr(pos);
}

string Multiply(string str, int num) {
    
    
	int carry = 0;
	for (int i = str.size() - 1; i >= 0; --i) {
    
    
		int current = num * (str[i] - '0') + carry;
		str[i] = current % 10 + '0';
		carry = current / 10;
	}
	if (carry != 0) {
    
    
		str = "1" + str;
	}
	return str;
}

string Add(string str, int num) {
    
    
	int carry = num;
	for (int i = str.size() - 1; i >= 0; --i) {
    
    
		int current = (str[i] - '0') + carry;
		str[i] = current % 10 + '0';
		carry = current / 10;
	}
	if (carry != 0) {
    
    
		str = "1" + str;
	}
	return str;
}

int main() {
    
    
	string str;
	while(cin >> str){
    
    
		vector<int> binary;
		while (str.size() != 0) {
    
    
			int last = str[str.size() - 1] - '0';
			binary.push_back(last % 2);
			str = Divide(str, 2);
		}
		string ans = "0";
		// 转的是题目要求的逆序二进制
		for (int i = 0; i < binary.size(); ++i) {
    
    
			ans = Multiply(ans, 2);
			ans = Add(ans, binary[i]);
		}
		cout << ans << endl;
	}
	return 0;
}
  • 字符串的乘法、加法 ——> 实现字符串数字(当数位较高int表示不了时,用string表示)的二(N)进制转十进制:从“0”开始,从(字符串的低位到高位,数字的高位到低位)低位到高位依次加上各数位的值,并不断乘二(N)
  • 字符串除法——> 实现字符串数字十进制转二(N)进制:对于字符串(对一个数模x相当于该数最低位模x)不断模二(N)得到二(N)进制最低数位的值,并除二,实现高位数值向低位移动。
  • 注意在实现字符串加减乘除时,各位数字的int到char的转化

例题6.4 进制转换2

KY235 进制转换2

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <cstdio>
#include <string>
#include <stack>

using namespace std;

char int2char(int x) {
    
    
	if (x < 10) {
    
    
		return x + '0';
	}
	else {
    
    
		return x - 10 + 'a'; // 十六进制大小写都可以
	}
}

int char2int(char c) {
    
    
	if (c <= '9' && c >= '0') {
    
    
		return c - '0';
	}
	else {
    
    
		return c - 'A' + 10;
	}
}

int main() {
    
    
	int m, n;
	scanf("%d %d", &m, &n);
	string str;
	cin >> str;
	long long number = 0; 
	for (int i = 0; i < str.size(); ++i) {
    
     
		number *= m;
		number += char2int(str[i]);
	}
	stack<char> result;
	while (number != 0) {
    
    
		result.push(int2char(number % n)); 
		number /= n;
	}
	while (!result.empty()) {
    
    
		printf("%c", result.top());
		result.pop();
	}
	printf("\n");
	return 0;
}

习题6.1 八进制

KY230 八进制

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <stack>

using namespace std;

int main() {
    
    
	int n;
	while (scanf("%d", &n) != EOF) {
    
    
		stack<int> result;
		while (n != 0) {
    
    
			result.push(n % 8);
			n /= 8;
		}
		while (!result.empty()) {
    
    
			printf("%d", result.top());
			result.pop();
		}
		printf("\n");
	}
	return 0;
}

华科这道题居然标的较难,这个牛客这个题目难度评级系统不可信

习题6.2 又一版A + B

KY135 又一版 A+B

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <iostream>
#include <string>
#include <stack>

using namespace std;

int main() {
    
    
	int m;
	unsigned int A, B;
	while (scanf("%d%", &m) != EOF) {
    
    	
		if (m == 0) {
    
    
			break;
		}
		scanf("%u %u", &A, &B);
		unsigned int sum = A + B;
		stack<int> result;
		
		if (sum == 0) {
    
    
			result.push(0);
		}
		else {
    
    
			while (sum != 0) {
    
    
				result.push(sum % m);
				sum /= m;
			}
		}

		while (!result.empty()) {
    
    
			printf("%d", result.top());
			result.pop();
		}
		printf("\n");
	}
	return 0;
}

我发现我真是学蒙了,超过int的表示范围就用unsigned啊,转什么string??
本人特长:简单问题复杂化

  • 利用unsigned int printf(%u)

习题6.3 进制转换(有空再看看)

KY80 进制转换

#include<iostream>

using namespace std;

int main(){
    
    
    int a;
    while(scanf("%0xd",&a)!=EOF) cout<<a<<endl;
    return 0;
}

同上,我最擅长简单问题复杂化了。有空再看看自己写的错误代码ovo

  • 输出结果一样,不用考虑类型~~

习题6.4 数制转换(有空再看看)

KY56 数制转换

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

using namespace std;

char IntToChar(int n) {
    
    
  if (n >= 10) {
    
    
    return n - 10 + 'A';
  } else {
    
    
    return n + '0';
  }
}

int CharToInt(char c) {
    
    
  if (c <= 'f' && c >= 'a')  {
    
    
    return c - 'a' + 10;
  } else if (c <= 'F' && c >= 'A') {
    
    
    return c - 'A' + 10;
  } else if (c <= '9' && c >= '0') {
    
    
    return c - '0';
  }
  return 0;
}

int main() {
    
    
  string str,result;
  int a, b;
  while (cin >> a >> str >> b) {
    
    
    int sum = 0, k = 1;
    for (int i = str.size() - 1; i >= 0; --i) {
    
    
      sum += k * CharToInt(str[i]);
      k *= a;
    }
    while (sum) {
    
    
      result = IntToChar(sum % b) + result;
      sum /= b;
    }
    // reverse(result.begin(), result.end());
    cout << result << endl;
  }
  return 0;
}

part 2 最大公约数和最小公倍数

例题6.5 最大公约数

KY161 最大公约数

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>

using namespace std;

int GCD(int a, int b) {
    
    
	if (b == 0) {
    
    
		return a;
	}
	else {
    
    
		return GCD(b, a % b);
	}
}

int main() {
    
    
	int a, b;
	while (scanf("%d %d", &a, &b) != EOF) {
    
    
		printf("%d\n", GCD(a, b));
	}
	return 0;
}
  • 最大公约数:(a, b)的公约数和(b, a mod b)的公约数一样
    在这里插入图片描述

例题6.6 最小公倍数

在这里插入图片描述

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>

using namespace std;

int GCD(int a, int b) {
    
    
	if (b == 0) {
    
    
		return a;
	}
	else {
    
    
		return GCD(b, a % b);
	}
}
int main() {
    
    
	int a, b;
	while (scanf("%d %d", &a, &b) != EOF) {
    
    
		printf("%d\n", a * b / GCD(a, b));
	}
	return 0;
}
  • a,b两个数的最小公倍数为两数的成绩除以他们的最大公约数

习题6.5 最简真分数

KY35 最简真分数

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>

using namespace std;

int arr[601];

int GCD(int a, int b) {
    
    
	if (b == 0) {
    
    
		return a;
	}
	else {
    
    
		return GCD(b, a % b);
	}
}

int main() {
    
    
	int n;
	while (scanf("%d", &n) != EOF) {
    
    
		for (int i = 0; i < n; ++i) {
    
    
			scanf("%d", &arr[i]);
		}
		int count = 0;
		for (int i = 0; i < n; ++i) {
    
    
			for (int j = i + 1; j < n; ++j) {
    
    
				if (GCD(arr[i], arr[j]) == 1) {
    
    
					count++;
				}
			}
		}
		printf("%d\n", count);
	}
	return 0;
}

part 3 质数

例题6.7 素数判定

KY163 素数判定

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <cmath>

using namespace std;

int main() {
    
    
	int n;
	while (scanf("%d", &n) != EOF) {
    
    
		bool flag = true;
		if (n >= 2) {
    
    
			for (int i = 2; i <= sqrt(n); ++i) {
    
    
				if (n % i == 0) {
    
    
					flag = false;
					break;
				}
			}
		}
		else {
    
    
			flag = false;
		}
		if (flag == true) {
    
    
			printf("yes\n");
		}
		else {
    
    
			printf("no\n");
		}
	}
	return 0;
}
  • 质数/素数:只能被其自身和1整除的正整数。测试到sqrt(n)即可。(存在一个大于sqrt(n)的因数,则必存在一个小于sqrt(n)的因数)
  • sqrt()头文件,cmath

例题6.8 素数

KY183 素数

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <vector>

using namespace std;

const int MAXN = 10001;
bool isPrime[MAXN];

vector<int> Prime;

void Initial() {
    
    
	for (int i = 0; i < MAXN; ++i) {
    
    
		isPrime[i] = true;
	}
	isPrime[0] = false;
	isPrime[1] = false;
	for (int i = 2; i < MAXN; ++i) {
    
    
		if (!isPrime[i]) {
    
    
			continue;
		}
		Prime.push_back(i);
		for (int j = i * i; j < MAXN; j += i) {
    
    
			isPrime[j] = false;
		}
	}
	return ;
}

int main() {
    
    
	int n;
	Initial();
	while (scanf("%d", &n) != EOF) {
    
    
		bool flag = false;
		for (int i = 0; i < Prime.size() && Prime[i] < n; ++i) {
    
    
			if (Prime[i] % 10 == 1) {
    
    
				printf("%d ", Prime[i]);
				flag = true;
			}
		}
		if (!flag) {
    
    
			printf("-1");
		}
		printf("\n");
	}
	return 0;
}
  • 素数筛法:遍历2到10000(bound)的所有整数,如果当前整数未被标记为非素数,则判定为素数。(0,1非素数);找到一个素数,并将它的所有倍数(小于bound)标记为非素数(2开始)
  • 倍数标记非素数时,从i的平方开始遍历,每次+一个i
    在这里插入图片描述
  • 抽出一个Initial函数,算出bound以内的所有素数~
void Initial() {
    
    
	for (int i = 0; i < MAXN; ++i) {
    
    
		isPrime[i] = true;
	}
	isPrime[0] = false;
	isPrime[1] = false;
	for (int i = 2; i < MAXN; ++i) {
    
    
		if (!isPrime[i]) {
    
    
			continue;
		}
		Prime.push_back(i);
		for (int j = i * i; j < MAXN; j += i) {
    
    
			isPrime[j] = false;
		}
	}
	return ;
}

习题6.6 Prime Number

KY110 Prime Number

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <vector>

using namespace std;

const int MAXN = 100001;
bool isPrime[MAXN];

vector<int> prime;

void Initial() {
    
    
	for (int i = 0; i < MAXN; ++i) {
    
    
		isPrime[i] = true;
	}
	isPrime[0] = false;
	isPrime[1] = false;
	for (int i = 2; i < MAXN; ++i) {
    
    
		if (!isPrime[i]) {
    
    
			continue;
		}
		prime.push_back(i);
		for (int j = i * i; j < MAXN; j += i) {
    
    
			isPrime[j] = false;
		}
	}
	return;
}

int main() {
    
    
	int n;
	Initial();
	while (scanf("%d", &n) != EOF) {
    
    
		printf("%d\n", prime[n - 1]);
	}
	return 0;
} 
  • vs2019堆栈保留大小默认1M,写代码时尽量别开太大的静态数组,编译会炸。

part 4 分解质因数

例题6.9 质因数的个数

KY7 质因数的个数

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <vector>
#include <cmath>

using namespace std;

const int MAXN = 1e5 + 1;
bool isPrime[MAXN];

vector<int> prime;

void Initial() {
    
    
	for (int i = 0; i < MAXN; ++i) {
    
    
		isPrime[i] = true;
	}
	isPrime[0] = false;
	isPrime[1] = false;
	for (int i = 2; i < MAXN; ++i) {
    
    
		if (!isPrime[i]) {
    
    
			continue;
		}
		prime.push_back(i);
		for (int j = i * i; j < MAXN; j += i) {
    
    
			isPrime[j] = false;
		}
	}
	return;
}

int main() {
    
    
	int n;
	Initial();
	while (scanf("%d", &n) != EOF) {
    
    
		int answer = 0;
		for (int i = 0; i < prime.size() && prime[i] < n; ++i) {
    
    
			int factor = prime[i];
			while (n % prime[i] == 0) {
    
    
				n /= factor;
				answer++;
			}
		}
		if (n > 1) {
    
    
			answer++;
		}
		printf("%d\n", answer);
	}
	return 0;
}
  • 质因数
    在这里插入图片描述

习题6.7 约数的个数

KY3 约数的个数

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <iostream>
using namespace std;


int numOfDivide(long num) {
    
    
	int count = 0;
	long i;
	for (i = 1; i * i < num; ++i) {
    
    
		if (num % i == 0) {
    
    
			count += 2;
		}
	}
	if (i * i == num) {
    
    
		count++;
	}
	return count;
}

int main() {
    
    
	int n;
	long num;
	while (scanf("%d", &n) != EOF) {
    
    
		for (int i = 0; i < n; ++i) {
    
    
			cin >> num;
			printf("%d\n", numOfDivide(num));
		}		
	}
	return 0;
}

习题6.8 整除问题(有空再看看)

KY105 整除问题

#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN=1010;
const int INF=(1<<31)-1;
//素数筛
bool p[MAXN]={
    
    false};//未被筛选
vector<int> prime;
void getPrime()
{
    
    
    p[0]=p[1]=true;//被筛去,不是素数
    for(int i=2;i<MAXN;i++)
    {
    
    
        if(p[i]==false)//未被筛去,是素数
        {
    
    
            prime.push_back(i);
            for(int j=i+i;j<MAXN;j+=i)
                p[j]=true;
        }
    }
}
int nFac[MAXN]={
    
    0};//记录n!的质因数分解后的结果,n!存在质因数i,则aFac[i]=指数
int aFac[MAXN]={
    
    0};//记录a的质因数分解的结果,a存在质因数i,则aFac[i]=指数
//对n!质因子分解
void getnFac(int n)
{
    
    
    for(int i=0;prime[i]<=n;i++)
    {
    
    
        int pow=0;
        int tempn=n;
        while(n!=0)
        {
    
    
            pow+=n/prime[i];
            n/=prime[i];
        }
        nFac[prime[i]]=pow;
        n=tempn;//还原n
    }
}
//对a质因子分解
int getaFac(int a)
{
    
    
    int ans=INF;
    int sqr=sqrt((double)a);
    for(int i=0;prime[i]<=sqr;i++)
    {
    
    
        while(a%prime[i]==0)
        {
    
    
            aFac[prime[i]]++;
            a=a/prime[i];
        }
        //prime[i]是a的质因子
        if(aFac[prime[i]]>0)
        {
    
    
            //prime[i]不是n!的质因子
            if(nFac[prime[i]]==0)
                ans=0;
            //取相同质因子的指数相除最小的
            else if(nFac[prime[i]]/aFac[prime[i]]<ans)
                ans=nFac[prime[i]]/aFac[prime[i]];
        }
        if(a==1)
            break;
    }
    if(a!=1)
    {
    
    
        //剩下一个大于根号a的数是a的质因子
        aFac[a]++;
        //剩下一个大于根号a的数不是n!的质因子
        if(nFac[a]==0)
            ans=0;
        //取相同质因子的指数相减最小的
        else if(nFac[a]/aFac[a]<ans)
            ans=nFac[a]/aFac[a];
    }
    return ans;
}
int main()
{
    
    
    int n,a;
    scanf("%d%d",&n,&a);
    getPrime();
    getnFac(n);
    int ans=getaFac(a);
    printf("%d",ans);
    return 0;
}

后续快速幂、矩阵与矩阵快速幂、高精度整数有时间再看,很难考具体实现

猜你喜欢

转载自blog.csdn.net/weixin_44145782/article/details/119906556
今日推荐