安徽省2015年“京胜杯”大学生程序设计竞赛First Blood

First Blood

1. 题目

Time Limit: 1000 MS

Memory Limit: 65536 KB

Total Submissions: 431 Accepted: 45

Description

盖伦是个小学一年级的学生,在一次数学课的时候,老师给他们出了一个难题:

老师给了一个正整数 n,需要在不大于n的范围内选择三个正整数(可以是相同的),使它们三个的最小公倍数尽可能的大。盖伦很想第一个解决这个问题,你能帮助盖伦拿到“first blood”吗?

Input

首先是一个正整数T,表示有T组测试数据

每组测试数据是一个正整数n(1<=n<=10^6)

Output

对于每组测试数据,输出最大的最小公倍数,每个输出单独占一行

Sample Input

2
9
7

Sample Output

504
210

Source

安徽省2015年“京胜杯”大学生程序设计竞赛


2. 算法描述

  1. 任意正整数v与v-1必定互质,v*(v-1)为两个数最小公倍数的最大值,v由最大范围n选起;
  2. 再选一数u,由于两数的最小公倍数与最大公约数之积等于两数之积,因此最小公倍数表示为(v*(v-1)*u)/gcd(v*(v-1),u),故在V选定的情况下最小公倍数的大小由u/gcd(v*(v-1),u)决定,因此u不能与v或v-1相同,u由v-2开始选取,直到v(v-1)*u<max_lcm为止(因为最小公倍数的最大值为三个数的乘积),记录这期间的最大的最小公倍数值max_lcm;
  3. v值减一,若max_lcm < v*(v-1)*(v-2),则u由v-2开始再进行一次第2步,完成后max_lcm 与 v*(v-1)*(v-2)比较,直到不满足“<”,输出max_lcm。

3. 注意事项

注意特殊值

  1. n=1时,v-1,v-2不存在,max_lcm=1;
  2. n=2时,v-2不存在,max_lcm=2;

4. 源代码

第一次提交:

//辗转相除法的版本
#include <iostream>
#include <algorithm>

using namespace std;

long long gcdByDiv(long long a,long long b);

int T;
long long n,v,v_lcm,u,max_lcm,temp_lcm;

int main(void)
{
   int t;
   cin >> T;
   for (t = 0; t < T; ++t)
   {
	  cin >> n;
	  v=n;
	  max_lcm=0;
	  v_lcm=v*(v-1);
	  while(v_lcm*(v-2) > max_lcm)
	  {
		 u=v-2;
		 while(v_lcm % u != 0)
		 {
			temp_lcm = v_lcm * u / gcdByDiv(v_lcm,u);
			if(temp_lcm > max_lcm) max_lcm = temp_lcm;
			u--;
		 }
		 v--;
	  }
	  cout << max_lcm << endl;
   }
   return 0;
}

long long gcdByDiv(long long a,long long b)
{
   long long c = a>b?a:b;
   long long result = a>b?b:a;
   long  long temp=0;

   c = c % result;
   while(c!=0)
   {
	  temp = c;
	  c = result;
	  result = temp;
	  c= c % result;
   }
   return result;
}

结果:
第一次提交结果

经过多次错误提交后改正了一些错误:
多次提交结果

最终通过源代码:

#include <iostream>
#include <algorithm>

using namespace std;

long long gcdByDiv(long long a,long long b);

int T;
long long n,v,v_lcm,u,max_lcm,temp_lcm;

int main(void)
{
    int t;
    cin >> T;
    for (t = 0; t < T; ++t)
    {
        cin >> n;
        v=n;
        max_lcm=0;

    
        if(v-1>0)
        {
            v_lcm=v*(v-1);
            if(v-2>0)
                u=v-2;
            else
                u=v-1;
        }
         else
        {
            v_lcm=v;
            u=v;
        }
        while(v_lcm*u > max_lcm)
        {
            //while(v_lcm % u != 0)
            while(v_lcm*u > max_lcm)
            {
                temp_lcm = v_lcm * u / gcdByDiv(v_lcm,u);
                if(temp_lcm > max_lcm) max_lcm = temp_lcm;
                u--;
            }
            v--;
            if(v-1>0)
            {
                v_lcm=v*(v-1);
                if(v-2>0)
                    u=v-2;
                else
                    u=v-1;
            }
            else
            {
                v_lcm=v;
                u=v;
            }
        }
        cout << max_lcm << endl;
    }
    return 0;
}

long long gcdByDiv(long long a,long long b)
{
    long long c = a>b?a:b;
    long long result = a>b?b:a;
    long  long temp=0;

    c = c % result;
    while(c!=0)
    {
        temp = c;
        c = result;
        result = temp;
        c= c % result;
    }
    return result;
}
posted @ 2016-04-30 09:27  夕音  阅读(1099)  评论(0)    收藏  举报