常用函数和代码
判断闰年
闰年:能被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;
}