2011 第二届蓝桥杯总决赛- 第三题 求1-n 的最小公倍数(n小于101)

 一、我们先考虑 当n< 41时, 结果是可以用long long 保存的。

       【1-7】的各个数因式分解是:2,3,2*2,5,2*3,7,2*2*2;最小公倍数:2*3*2   *5*    7* 2

1、设【1~n-1】的最小公倍数为a[n-1],如果 a[n-1]%n=0;那么a[n]=a[n-1];例如[1~5] 和[1~6];

2、否则,n这个数一定含有 必须乘到 a[n-1]上 的素因子,eg:8;

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define maxn 15
int prime[maxn] = {2,3,5,7,11,13,17,19,23,29, 31,37,41,43};
int main()
{
    int n,i,j,t,k;
    long long sum[42],temp;
    sum[1]=1;sum[2]=2;
        for(k=2; k<=40; k++)
        {
            if(sum[k-1]%k)//含有多的质因子
            {   temp=sum[k-1];
                for(i=0; prime[i]<=k; i++)
                  if(k%prime[i]==0)
                  {temp=temp*prime[i];}
               sum[k]=temp;
            }
            else
            sum[k]=sum[k-1];
        }
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
       printf("%lld\n",sum[n]-1);
    }
    return 0;
}

二、考虑到1-100的最小公倍数肯定超出__int64.所以需要转化成字符串问题来解

仔细观察会发现,【1-n】的最小公倍数,是【1-n-1】的最小公倍数乘以n的所有素因子中没有被【1-n-1】包含的素因子。
例如:【1-7】的最小公倍数是2*3*2*5*7,8=2*2*2,(8中2出现3次,【1-7】的素因子中只出现2次)那么【1-8】就是2*3*2*5*7*2

思路:(1)先求出1——>n 的因子;

           (2)然后只要做一个大数乘法即可。

#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
#define M 101
int factor[101];//存所有的因子;
struct  a{
  int c[43];//经输出测试,最长只有42
  int length;
  a()//构造函数
  {
     length=0;
  }
}ans[101];
void getfactor()
{
   int i,j;
   for(i=1;i<M;i++)
   {
      factor[i]=i;
      for(j=2;j<i;j++)
         if(factor[i]%factor[j]==0)
          factor[i]/=factor[j];
   }
}
void bigmulti()//高精度乘法
{
   int f=0,i,j,b;
   ans[1].c[0]=1;
   ans[1].length=1;
   for(i=2;i<=100;i++)
   {
      b=factor[i];
      for(f=0,j=0;j<ans[i-1].length;j++)
      {
         f=ans[i-1].c[j]*b+f;
         ans[i].c[j]=f%10;
         f/=10;
      }
      while(f)
      {
         ans[i].c[j]=f%10;
         f/=10;
         j++;
      }
      ans[i].length=j;
   }
}
void print(int i)//输出[1,n]的最小公倍数 ans[n]
{
   for(int j=ans[i].length-1;j>=0;j--)
      printf("%d",ans[i].c[j]);
   printf("\n");
}
int main()
{
    //freopen("ans.txt","w",stdout);
    getfactor();
    bigmulti();
    int n;
    while(cin>>n)
       print(n);
    return 0;
}

问题拓展:

1.判断1到n连续n个数的最小公倍数与1到n-1连续n-1个数的最小公倍数是否相等

思路:判断n是不是素数? (1)如果不是素数,找到一个i<=sqrt(n)的约数,判断  gcd((n/i),i)==1,那么输出YES;(2)否则,是素数,那么结果是NO。

代码:

#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
#define LL long long
LL gcd( LL a,LL b)
{
 return b==0?a:gcd(b,a%b);
}
int main()
{
    LL n;
    scanf("%I64d",&n);
    int flag=1;
    for(LL i=2; i*i<=n; i++)
       if(n%i==0)
        {
            LL tt=gcd((n/i),i);
            if(tt-1==0)
            {
                flag=0;
                printf("YES\n");
                break;
            }
        }
    if(flag) printf("NO\n");

   return 0;
}

2、hdu 2028  n个数的最小公倍数

思路:先求两个数的最大公约数,再求最小公倍数。

#include <cstdio>
#include <iostream>
using namespace std;
int Gcd(int  a,int b)
{
    return b==0?a:Gcd(b,a%b);
}
int main()
{
	int n;
	int ans,yueshu,temp;
	while(cin>>n)
	{
	  ans=1;
	  for(int i=0;i<n;i++)
	  {
	    scanf("%d",&temp);
	    yueshu=Gcd(ans,temp);
		ans=temp/yueshu*ans;//先除再乘,以防溢出
	  }
	  printf("%d\n",ans);
	}
   return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值