【XDOJ】C语言经典算法
先来个经典的水仙花数练练手
水仙花数
#include <stdio.h>
int narcissistic( int number )
{
int num,count=0,sum=0;
num=number;
while(num!=0)
{
sum+=(num%10)*(num%10)*(num%10);
num/=10;
}
if(sum==number)
return 1;
else
return 0;
}
void PrintN( int m, int n )
{
int i;
for(i=m+1;i<n;i++)
{
if(narcissistic(i))
{
printf("%d",i);
printf("\n");
}
}
}
int main()
{
int m, n;
scanf("%d %d", &m, &n);
if ( narcissistic(m) )
printf("%d is a narcissistic number\n", m);
PrintN(m, n);
if ( narcissistic(n) )
printf("%d is a narcissistic number\n", n);
return 0;
}
最小公倍数
从最大数开始递增,直至找到一个数模除两数都为0,break
for (j = t;; j++) {
if (j % a == 0 && j % b== 0) {
p[i] = j;
break;
}
实战练习
最小公倍数求和
对于 n 个正整数,分别求两相邻整数的最公倍数,得到 n-1 个值,然后求这 n-1 个值的和。
如给定 n=4 个整数 2 8 6 5,则相邻整数为(2,8),(8,6),(6,5),这三组数的最小公倍数分别为 8,24,30,所以最终输出 62。
#include <stdio.h>
int max(int a,int b)
{
if(a>b)
return a;
if(a<b)
return b;
}
int main()
{
int n,i,j,t,sum=0;
scanf("%d",&n);
int m[n];
for(i=0;i<n;i++)
scanf("%d",&m[i]);
for(i=0;i<n-1;i++)//注意此处区间-防止数组越界
{
t=max(m[i],m[i+1]);//找到两者中最大值
for(j=t;;j++)//从最大数开始
{
if(j%m[i]==0&&j%m[i+1]==0)//找到最小公倍数
{
sum+=j;
break;
}
}
}
printf("%d",sum);
}
最大公约数
从最小数开始递减 直到找到两数模除它都为0的数
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
int c = 0;
while(1)
{
scanf("%d%d",&a,&b);
c = (a>b)?b:a;
while((a%c != 0) || (b%c != 0))
{
c--;
}
printf("最大公约数为: %d \n",c);
}
return 0;
}
也可使用更相减损法和辗转相除法,这里不过多介绍
最大质约数
- 质数指除了1和它本身以外不能整除任和数的数字
- 最大质约数:能被所给数整除的最大质数
由定理,任意一个正整数n最多只有一个质因数大于根号n(即为n本身)
解决方案-辗转相除法- 从2到算术平方根遍历,若原数能除开此数,则记录原数除,依次递推,最终的数即为最大质约数
- 若最终不能除到1,则原数为最大质约数
- tips:sqrt的返回值是double型
- 此处较为稳妥的写法为
例:判断一个数是不是质数
bool find(int n)
{
int sql=(int)sqrt(1.0*n);//1.0*n的目的是 隐式转换成浮点数,开根号后再强制转换成整型
for(int i=2;i<=sql;i++)
{
if(n%i==0)//若有能除开的数,则不是质数
return false;
}
return true;
}
--来自CSDN博主「辉小歌」
在不考虑运行时间的情况下,可直接从n到2进行遍历
实战练习
和数最大质约数
一个由 N 位数字字符构成的字符串,表示 N 位整数(N 的位数不超过 9 位,可以为 1
位),编程完成该整数的分析处理任务,求出各位数字之和,在求出和数(大于 2 时)的最
大质约(可以是自身)。
#include <stdio.h>
#include <string.h>
#include <math.h>
void factor(char a[])
{
int i,l,t,sum=0,max,n;
l=strlen(a);
for(i=0;i<l;i++)
{
sum+=a[i]-'0';
}
if(sum<=2)
printf("sum <=2");
else
{
t=(int)sqrt(1.0*sum);//sqrt的使用
n=sum;
for(i=2;i<=t;i++)//从2到原数的算术平方数
{
while(n%i==0)//能整除时
{
max=i;//记录质约数
n/=i;
}//辗转相除法
if(n==1)
break;
}
if(n!=1)
max=sum;//如果不能除尽,则最大质约数为自身
printf("%d",max);
}
}
int main()
{
char m[10];
gets(m);
factor(m);
}
最后附赠一个金字塔
金字塔打印
编程完成M 行(3≤M≤10)字符C的金字塔形字符打印任务,各行分别打印1~M个字符C,形状如下图所示:
打印要求:打印为金字塔状,字符间空一个空格,行尾回车换行。
#include <stdio.h>
int main()
{
int m,i,j,k;
char n;
scanf("%d %c",&m,&n);
for(i=0;i<m;i++)//行
{
for(j=0;j<m-i-1;j++)
printf(" ");//输出空格
for(k=0;k<=i;k++)
printf("%c ",n);//输出字符
printf("\n");
}
}