做题基础~~~tips

1.拆分数字x(可以很大噢)

int x,a[10005],c=0;//a[]数组存放拆分出来的每个数字,c用于标记数字在数组里存放的位置
	scanf("%d",&x);
	while(x){
		a[c++]=x%10;
		x/=10;
	}
	for(int i=c-1;i>=0;i--)//正序输出
		printf("%d ",a[i]);

2.关于长度:

字符串数组长度:strlen()
整型数组长度:sizeof(arr)/sizeof( int )
注意:这里得到的是数组的总长度(即我们定义它的时候的大小),而不是数组中存放有意义的数据的个数
(实在不行就用定义一个量来追踪它就好啦)

3.查找一个数n的全部因子:(或者是因子的个数)

#include <bits/stdc++.h>
using namespace std;
int main(){
	int n; 
	int a[10005];//装n的所有因子
	int z=0;//辅助数组装因子的位置
	scanf("%d",&n);
	for(int i=1;i*i<=n;i++){
		if(n%i==0){
			a[z++]=i;
			if(i!=(n/i)){//因为是在n/2前找所以可以用这个方法来查找n/2后的符合条件的数
				a[z++]=n/i;
			}
		}
	}
	return 0;
}

4.找出一定范围x的素数

方法一:埃氏筛法

#include <bits/stdc++.h>
using namespace std;
int visit[100005]={0};//先假设全部都为素数
//0为素数   1为非素数 
int main() 
{
	int x;
	scanf("%d",&x);
	for(int i=2;i<=x;i++){
		if(!visit[i])
			for(int j=i*i;j<=x;j+=i) 
				visit[j]=1;
	}
	for(int i=2;i<=x;i++)
		if(!visit[i])
			printf("%d ",i);	 
    return 0;
}

这里的ii做了一个小优化,因为i(2 ~ i-1)在2~i-1时已经被筛去辽
但是,埃氏筛法有一个弊端,就是重复判断同一个数,重复筛去同一个数,这也会浪费时间,当数据很大时也可能会超时。
为了解决这个弊端,我们引进一种新的方法:欧拉筛法。

方法二:欧拉筛法

(它可以让每个合数只被它最小的质因子筛选一次!!!超厉害!!!他也太聪明了叭!!!!

#include <bits/stdc++.h>
using namespace std;
//设0为素数  1为非素数 
int visit[100005]={0};//访问每个位置,判断 
int prime[100005]={0};//储存  
int Prime(int x){
	int n=0;
	for(int i=2;i<=x;i++){
		if(!visit[i])
			prime[n++]=i;
		for(int j=0;j<n&&i*prime[j]<=x;j++){
			visit[i*prime[j]]=1;
			if(i%prime[j]==0) break;//这个得细细琢磨,是这个方法的精髓!!! 
		}
	}
	return n; //记录找到了多少个素数(n为素数总数+1) 
}
int main() 
{
	int x;
	scanf("%d",&x);
	int sum=Prime(x);
	for(int i=0;i<sum;i++){
		printf("%d ",prime[i]);
	}
	cout<<endl<<sum;
    return 0;
}

这个方法中i*prime[j] 以及i%prime[j]==0这两步 可以通过打印出每一步的过程来帮助我们理解。比如:
方便理解
我们可以看到,i在消去合数中的作用是:当做倍数来帮助代码找到合数并消去。
i%prime[j] == 0 break:当 i是prime[j]的倍数时,i = k * prime[j](k>1),如果继续 j++,i * prime[j+1] = prime[j] * k *prime[j+1],这里prime[j]是最小的素因子,当i = k * prime[j+1]时会重复此过程(变得麻烦且没必要),所以跳出循环。

5.判断是否为互质数/求两数最大公约数/最小公倍数

判断是否为质数:即求两个数的最大公约数(最后返回的b)是否为1
以下代码为求两数的最大公约数/最小公倍数,若为1则两数互质
辗转相除法:

int find(int a,int b){
	int cmp;
//	int aa=a,bb=b;
	if(a<b){
		cmp=a;
		a=b;
		b=cmp;
	}
	while(a%b){
		cmp=b;
		b=a%b;
		a=cmp;
	}
	return b;//最大公约数
//	return aa*bb/b;//最小公倍数:用两数的乘积除以两数的最大公约数
}

6.关于高精度

string对于高精度真的很友好,若不太懂请找找博客自行了解一下它的用法就好啦

高精度加法

noi:1.6 10大整数加法
题目中要考虑前导0

#include <bits/stdc++.h>
using namespace std;
string x,y;
int a[220],b[220],ans[220]; 
int main(){
    cin>>x>>y;
    int la=x.length();//string长度
    int lb=y.length();
    for(int i=0;i<la;i++){
    	a[la-i-1]=x[i]-'0';
	}
	for(int i=0;i<lb;i++){
		b[lb-i-1]=y[i]-'0';
	}
	int lc=max(la,lb);
	for(int i=0;i<lc;i++){
		ans[i]+=a[i]+b[i];
		ans[i+1]=ans[i]/10;//如果>=10就进位
		ans[i]%=10;//如果>=10就-10
	}
	if(ans[lc]) lc++;//考虑最高位是否存在进位
	while(ans[lc-1]==0&&lc>1) lc--;//如果有前导0长度就减去,且考虑到如果都是0就保留最后一个0
	for(int i=lc-1;i>=0;i--){
		cout<<ans[i];
	}
    return 0;
}

高精度减法

noi:1.6 11:大整数减法

#include <bits/stdc++.h>
using namespace std;
string x,y;
int a[220],b[220],ans[220]; 
int main(){
    cin>>x>>y;
    int la=x.length();
    int lb=y.length();
    if(la<lb || la==lb&&x<y){//string在两个长度相等的条件下可以自己通过字典序比较大小 
		swap(x,y);
		swap(la,lb);
		cout<<'-'; 
	}
    for(int i=0;i<la;i++){
    	a[la-i-1]=x[i]-'0';
	}
	for(int i=0;i<lb;i++){
		b[lb-i-1]=y[i]-'0';
	}
	int lc=max(la,lb);
	for(int i=0;i<lc;i++){
		if(a[i]<b[i]){
			a[i]+=10;
			a[i+1]--;
		}
		ans[i]=a[i]-b[i];
	}
	if(ans[lc]) lc++;
	while(ans[lc-1]==0&&lc>1) lc--;
	for(int i=lc-1;i>=0;i--){
		cout<<ans[i];
	}
    return 0;
}

高精度乘法(A*B)

P1303 A*B Problem
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
string x,y;
int a[100010],b[100010],ans[100010]; 
int main(){
    cin>>x>>y;
    int la,lb,lc;
    la=x.length();
	lb=y.length();
    lc=la+lb;
    for(int i=0;i<la;i++){
    	a[la-i-1]=x[i]-'0';
	}
	for(int i=0;i<lb;i++){
    	b[lb-i-1]=y[i]-'0';
	}
	for(int i=0;i<la;i++){
		for(int j=0;j<lb;j++){
			ans[i+j]+=a[i]*b[j];
			ans[i+j+1]+=ans[i+j]/10;
			ans[i+j]%=10;
		}
	}
	while(ans[lc-1]==0&&lc>1) lc--;//去掉前导0
	for(int i=lc-1;i>=0;i--){
		cout<<ans[i];
	}
    return 0;
}

7.玩转二进制~(一些位运算的实用小技巧)

众所周知位运算可以让某些判断进行的更快~ 下面我们就来康康它的一些作用叭~

1.判断a的第i位为1/0:

a&(1<<i)

2.判断a是否为2的次方:

a&(a-1)//结果为0:是;结果为1:否

3.取a最低位上的1:

a&-a

举个栗子:
20(10)=10100(2)
20&-20=100(2)

4.将a的第i位变为0:

a&(0<<i)

1.将a的第i位变为1:

a|(1<<i)

2.求a的相反数:

~a+1

异或

1.将a的第i位取反:

a^(1<<i)

2.交换a b两个数的值:

a^b^b=a

或者

a^=b;
b^=a;
a^=b;
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值