训2 进制转换、位运算、快速幂

1.进制转换

了解数制

数制是一种用一组固定的符号和统一的规则来表示数值的方法。包含两个基本要素:基数和位权

基数表示数制中使用的数字符号的个数。

位权表示每个位置上数字的价值。

常见的进制

常见的进制转换

任意进制转十进制C++

#include<iostream>
#include <cmath>
using namespace std;
int p, sum, tmp;
int main() {
	string s;
	
	cin >> s;
	cin>>p; 
	int m;
	for (int i= s.length()-1;i >= 0;i--) {
		if (s[i] >= 'A' && s[i] <= 'F') {//如果为字母,要转换成其代表的数m=s[i]-'A'+ 10;
			m = s[i] - 'A' + 10;
		}
		else {

			m = s[i] - '0';           //小于10,转换成数字 
			sum += m * pow(p,tmp);     //乘以位权,然后相加。 
			tmp++;
		}
	}
	cout << sum;
	return 0;
}

十进制转任意进制

//十进制转任意进制
#include<bits/stdc++.h>
using namespace std;
int n,p;
string s;
int main(){
	cin>>n>>p;
	while(n){
		int tmp=n%p;
		if(tmp>=10){
			s+=tmp-10+'A';//大于等于10的话进行字符进制转换 
		}else{
			s+=tmp+'0';//否则直接加0变正常字符数字 
		}
		n/=p;//按照二进制短除法,除以p更新进制。	
	}
	for(int i=s.length()-1;i>=0;i--){
		cout<<s[i];
	}
	return 0;
} 

任意进制互相转换

思路:

可以把十进制当作中介,先从任意进制转为十进制,再从十进制转为任意进制。(集合两个的思路)

//任意进制相互转换
#include<bits/stdc++.h>
using namespace std;
int p,q,sum,tmp;
string a,ans;
int main(){
	cin>>p>>a>>q;
	int m;
	for (int i= a.length()-1;i >= 0;i--) {
		if (a[i] >= 'A' && a[i] <= 'F') {//如果为字母,要转换成其代表的数m=s[i]-'A'+ 10;
			m = a[i] - 'A' + 10;
		}
		else {

			m = a[i] - '0';           //小于10,转换成数字 
			sum += m * pow(p,tmp);     //乘以位权,然后相加。 
			tmp++;
		}}
		while(sum){
		int tmp=sum%p;
		if(tmp>=10){
			ans+=tmp-10+'A';//大于等于10的话进行字符进制转换 
		}else{
			ans+=tmp+'0';//否则直接加0变正常字符数字 
		}
		sum/=p;//按照二进制短除法,除以p更新进制。	
	}
		for(int i=ans.length()-1;i>=0;i--){
		cout<<ans[i];
	}
	
	
	return 0;
} 

2.位运算

位运算就是基于整数的二进制表示进行的运算。由于计算机内部就是以二进制来存储数据,位运算是相当快的。

基本的位运算共5种,分别为按位与、按位或、按位异或、按位取反、左移和右移。

位运算简介:

有关2的幂的运算的应用

将一个数乘(除)以2的非负整数次幂(向下取整)

int mul_pow(int n,int m){
	return n<<m;
}
int dev_pow(int m,int n){
	return n>>m;
}

3.快速幂

快速幂算法的核心思想就是每一步都把指数分成两半,而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,所需要执行的循环次数也变小,而最后表示的结果却一直不会变。

让我们先来看一个简单的例子:(来自百度百科)

3^10=3*3*3*3*3*3*3*3*3*3

3^10=(3*3)*(3*3)*(3*3)*(3*3)*(3*3)

3^10=(3*3)^5

3^10=9^5

9^5=(9^4)*(9^1)

9^5=(6561^1)*(9^1)

以下以求a的b次方来介绍 

把b转换成二进制数

该二进制数第i位的权为

例如

11的二进制是1011

因此,我们将a¹¹转化为:

快速幂的优势,给出一个例子:

问:

那么我们的暴力算法:

简单优化:利用取模性质,每次相乘就进行取模。

他的时间复杂度依旧没有优化:

这里用到我们刚才说到的快速幂。

红色为当底数的指数为偶数时,那么直接乘以底数的二倍,指数减半

黄色为当底数的指数为奇数时,需要先拿出一个底数,指数减一,然后对剩余的偶数指数进行底数相乘,指数减半。

模板代码c++

//快速幂
#include<iostream>
using namespace std;
typedef long long ll;
ll fast_power(int a,int b,int c){
   ll ans=1;
   a=a%c;
   while(b){
   	if(b&1){
   		ans=(ans*a)%c;
	   }
	   a=(a*a)%c;
	   b>>=1;
   }
	return ans;	
}
int main(){
	ll a,b,c;
	cin>>a>>b>>c;
	cout<<a<<"^"<<b<<" mod "<<c<<"="<<fast_power(a,b,c);	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

入门两年的练习生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值