常用函数和代码段

判断闰年

闰年:能被4整除且不能被100整除或者能被400整除的年份是闰年。
如:2000年,2004年,2008年是闰年,而1900年,1901年不是闰年。
代码

//判断闰年
bool leapyear(int n){
    
    
	if(n%4==0&&n%100!=0||n%400==0)
		return true;
	else 
		return false;
} 

最大公约数、最小公倍数

最大公约数用辗转相除法,最小公倍数为两数之积除以最大公约数。

//最大公约数
//迭代写法 
int gcd(int a,int b){
    
    
	int c;
	while(b!=0){
    
    
		c=a%b;
		a=b;
		b=c;
	} 
	return a;
} 

//递归写法
int gcd(int a,int b){
    
    
	return !b?a:gcd(b,a%b);
} 

//最小公倍数
int f(int a,int b){
    
    
	return  a*b/gcd(a,b);
}

判断素数

判断一个大于1的整数n是不是素数,只要保证在[2,sqrt(n)]之间没有n的因子。
代码

//素数判断
bool isPrime(int n){
    
    
	if(n==1)return false; //特殊情况1 
	
	for(int i=2;i*i<=n;i++){
    
     //i*i<=n保证i是小于等于sqrt(n)的
		if(n%i==0) return false;
	}
	return true;
} 

素数筛法

从小到大枚举所有数,对于每一个素数,筛去它的所有倍数,剩下的就都是素数了。
当从小到大枚举某数时,如果这个数没有被前面出现的素数筛去,说明这个数一定是素数。

#include<iostream>
#include<string.h>
using namespace std;

const int maxn=100001;
int prime[maxn]; 
//素数筛法
void find_prime(){
    
    
	memset(prime,0,sizeof(prime));	//给数组prime赋初值0,表示没有被筛去 
	prime[0]=prime[1]=1;	//如果数组的值为1表示不是素数 
	for(int i=2;i<maxn;i++){
    
    
		if(prime[i]==0){
    
    
			for(int j=i*2;j<maxn;j+=i)
				prime[j]=1;
		}
	}
}

int main()
{
    
    
	find_prime();
	for(int i=0;i<maxn;i++)
		if(prime[i]==0)
			cout<<i<<' ';
	return 0; 
 } 

质因子分解

一、理论部分

唯一质因子分解定理:

任何一个大于1的整数n都可以分解成若干个素因数的连乘积,如果不计各个素因数的顺序,那么这种分解是惟一的,即若n>1,则有 n=p1e1p2e2……pnen (其中p1,p2,……为素数,e1,e2为是每个素数的指数)

n的因子的个数为(e1+1)(e2+1)……(en+1)

所以根据质因子分解定理,可以将一个合数写成多个素数相乘的形式,并由此计算这个合数的因子的个数。

问题:合数n的因子的个数为什么是(e1+1)(e2+1)……(en+1)?
p10p20……pn0
p10p20……pn1
p10p20……pn2
……
……
……
p1np2n……pnn
上面的这些全都是合数n的因子,所以一共有(e1+1)(e2+1)……(en+1)个因子


二、代码实现

由于每个质因子都可以不止出现一次,所以可以定义一个结构体存放质因子及其个数。用一个结构体数组表示一个合数的质因子分解的结果。

typedef struct node{
    
    
	int x;	//x为质因子
	int cnt;	//cnt记录出现个数
}A;
A a[10];  //一般来说,数组大小为10就足够

考虑到2x3x5x7x11x13x17x19x23x29就已经超过了int表示范围,因此对于一个int型范围的数来说,数组a的大小只需要开到10就可以了。

两个结论:

1.对于一个正整数n来说,如果它存在1和本身之外的因子,那么一定是在sqrt(n)的左右成对出现。
2.对于一个正整数n来说,如果它存在[2,n]范围内的质因子,要么这些质因子全部小于sqrt(n),要么只存在一个大于sqrt(n)的质因子,而其余质因子全部小于等于sqrt(n)。

对于结论1,很容易理解如果a是n的因子,那么(n/a)也是n的因子。
对于结论2,根据质因子唯一分解定理,一个大于1的正整数的质因子分解是唯一的,所以假设有两个大于sqrt(n)的质因子,则这两个质因子的乘积一定大于n,这与前提相冲突。所以最多只有一个大于sqrt(n)的质因子。

结论2对进行质因子分解提供了一个很好的思路:
(1)枚举1~sqrt(n)范围内的所有质数p,判断p是否是n的因子。
如果p是n的因子,那么给数组a中增加质因子p,并初始化其个数为0,然后只要p还是n的因子,就让n不断除以p,每次操作令p的个数加1,直到p不再是n的因子位置。
如果p不是n的因子,就直接跳过。
(2)如果在上面步骤结束后n仍然大于1,说明n有且仅有一个大于sqrt(n)的质因子(n本身),这时需要把这个质因子加入数组a中,并令其个数为1 。

#include<iostream>
#include<cstring>
#include<cmath> 
using namespace std;

typedef struct node{
    
    
	int x;		//质因子 
	int cnt; 	//指数 
}Node; 

Node a[15]; //用一个数组存储某个数的质因子及其次数 
int t;

//质因子分解
int p[101];
int  prime[100]; //用来存储素数表 
int pt=0;

void find_prime(){
    
     //找出100以内的所有素数
	memset(p,0,sizeof(p));
	for(int i=2;i<=100;i++){
    
    
		if(p[i]==0){
    
    
			prime[pt]=i; //将找到的素数放入素数表 
			pt++;
			
			for(int j=i+i;j<=100;j+=i) //筛去素数所有倍数 
				p[j]=1; 
		}
	}
} 

void factor(int n){
    
    //求n的质因子分解 
	t=0; 
	int sqrt_n=int(sqrt(n*1.0)); 
	for(int i=0;i<pt;i++){
    
    
		if(prime[i]>sqrt_n)  break; //边界 
		
		if(n%prime[i]==0){
    
    
			a[t].x=prime[i];
			while(n%prime[i]==0){
    
    
				a[t].cnt++; 
				n/=prime[i];	
			}
			t++;
		}
	}
	
	if(n==1) return;
	else{
    
    
		a[t].x=n;
		a[t].cnt=1;
		t++;
		return;
	}
} 


int main()
{
    
    
	find_prime();  //得到素数表
	int n;
	while(true){
    
    
		cin>>n;
		for(int i=0;i<10;i++)
			a[i].x=a[i].cnt=0;
		factor(n);
		//输出质因子分解结果
		cout<<"\t"<<n<<"="; 
		for(int i=0;i<t-1;i++)
			cout<<a[i].x<<"^"<<a[i].cnt<<"+";
		cout<<a[t-1].x<<"^"<<a[t-1].cnt<<endl;
	}
	
	return 0;
 } 

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45382645/article/details/114108360