枚举是根据所提出的内容,一一列出该问题的所有可能的解,并在逐一列出的过程中,检验每个可能解是否是问题的真正解,不满足就继续判断下一个。
可以用枚举法解决的问题有以下特点:1.枚举范围是有穷的。2.检验条件确定。
例一:输出正整数n的因数
枚举范围[1,n]
枚举条件:n%i==0
输入:35 输出:1 5 7 35
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
if(n%i==0)
{printf("%d ",i);}
}
return 0;
}
👀如果输出的是1,5,7,35 应该怎么修改呢?
并不能直接printf(",%d",i);直接在%d前后加上逗号
所以要么把1拿出来单独考虑,要么把35拿出来单独考虑
printf("%d",1);
for(int i=2;i<=n;i++)
{
if(n%i==0)
{printf(",%d",i);}
或者
for(i=1;i<n;i++)
{
if(n%i==0)
{printf("%d,",i);}
}
printf("%d",n);
例二:统计正整数因数的个数
非常简单 多引入一个s,修改一下就ok了
#include <stdio.h>
int main()
{
int n;
int s= 0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
if(n%i==0)
{s=s+1;}
}
printf("%d",s);
return 0;
}
素数(质数)
一个大于1的自然数,除了1和它本身不能被其他自然数整除的数。
素数的判断方法😐❓
1:定义法:统计整数n因数个数,如果恰好为2,则是素数。
2:试除法:枚举[2,n)的每个数i,判断i是否能整除n
定义法(只要在例二的基础上 再加一个if判断就可以了
#include <stdio.h>
int main()
{
int n;
int s= 0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
if(n%i==0)
{s=s+1;}
}
if(s==2){
printf("%d是素数",n);
}
else{
printf("%d不是素数",n);
}
return 0;
}
试除法
#include <stdio.h>
int main()
{
int n,i;
int f=1;//假设n为素数
scanf("%d",&n);
for(i=2;i<n;i++)
{if(n%i==0)
f = 0;//可以整除
break;
}
if(f==1) {
printf("yes");}
else {
printf("no");}
return 0;
}
一个一个试的话当输入的数字比较大时速度较慢慢,如何优化呢?😕
6=1*6=2*3
12=1*12=2*6=3*4 因数成对出现 只枚举小的因数即可减少循环次数
循环到平方根即可
#include <stdio.h>
int main()
{
int n,i;
int f=1;//假设n为素数
scanf("%d",&n);
for(i=2;i<=n/i;i++)
//或改为i*i<=n(但是当i的数目比较大时i*i可能会爆掉
//或i<=sqrt(n)()但是要引入数学库函数
{if(n%i==0)
f = 0;//可以整除
break;
}
if(f==1&&n>1) //1的情况要单独考虑且上一步i赋值不能赋为1 不然1就终止循环了
{
printf("yes");}
else {
printf("no");}
return 0;
}
完美数
所有真因子(除了自身以外的约数)的和,恰好等于它本身。
6=1+2+3
6=1+2+4+7+14
#include <stdio.h>
int main()
{
int n;
int s= 0;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
if(n%i==0)
{
s=s+i;
}
}
if(s==n)
{
printf("yes");
}
else
{
printf("no");
}
return 0;
}
最大公约数
定义法
#include <stdio.h>
int main()
{
int a,b,t;
scanf("%d %d",&a,&b);
//a和b的大小不确定 先把a,b大小判断出来
if(a>b)
{
t=a;b=t;a=b;
}
//for(int i=1;i<=a;i++)不能这样写 比如4和8 i增加到2时就已经成立了
for(int i=a;i>0;i--)//i要大于0 才能满足比如两个数均是质数时最大公因数为1的情况
{
if(a%i==0&&b%i==0)
{
printf("%d",i);
break;//这里一定要加break 不然循环不终止 i减小到下一个公约数又会输出
}
}
return 0;
}
辗转相除法(欧几里得算法)
最小公倍数
计算A/B+C/D
输入A、B、C、D四个整数(0≤A<10000,0<B<10000,0≤C<10000,0<D<10000)
计算,要求计算结果为最简分式(分子、分母均为非负整数)
输入: 1 2 1 3
输出 :5 6
//计算A/B+C/D
#include <stdio.h>
int main()
{
int A,B,C,D;
scanf("%d %d %d %d",&A,&B,&C,&D);
int x = B*D;//分母
int y = A*D+B*C;//分子
int n;
if(x>y)
{n=x;}
else
{n=y;}
// 用这个更简单 n = x > y ? x : y;
//这一步是为了判断分子和分母的大小
//后面化简的时候同时除以的数不能比大数大
for(int i=1;i<n;i++)// (1)
{
if(x%i==0&&y%i==0)
{
x=x/i;y=y/i;//同时除以公约数化简
i=1;//返回到(1)的位置执行i++ 也就是从(1+1)2继续 比如12/18除一次2之后还可以再除一次2 而只用i++只能往上
}
}
printf("%d %d ",y,x);
return 0;
}
将正整数N分解为素数因子的连乘式
输入:6
输出:2*3