ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于CodeForces Round #696(Div.2)B题心得

2021-01-27 18:33:48  阅读:259  来源: 互联网

标签:arr 696 int CodeForces ++ num Div.2 integer include


2021-01-27 18:32:45

题目描述大致如下:

题目传送门

B. Different Divisors

time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output  

Positive integer x is called divisor of positive integer y, if y is divisible by x without remainder. For example, 1 is a divisor of 7 and 3 is not divisor of 8.

We gave you an integer dd and asked you to find the smallest positive integer a, such that

  • a has at least 4 divisors;
  • difference between any two divisors of aa is at least d.
Input

The first line contains a single integer t (1≤t≤3000) — the number of test cases.

The first line of each test case contains a single integer d(1≤d≤10000).

Output

For each test case print one integer a — the answer for this test case.

Example input
2
1
2
output
6
15
Note

In the first test case, integer 6 have following divisors: [1,2,3,6]. There are 4 of them and the difference between any two of them is at least 1. There is no smaller integer with at least 4 divisors.

In the second test case, integer 15 have following divisors: [1,3,5,15]. There are 4 of them and the difference between any two of them is at least 2.

The answer 12 is INVALID because divisors are [1,2,3,4,6,12]. And the difference between, for example, divisors 2 and 3 is less than d=2.

 于是,作为蒟蒻的我就开始了思考:(把待求的数设为k)
  1. 首先,这个除数可以为其自身和1.也就是说,其只需至少有两个其他的数被它整除。
  2. 我只需要遍历每一个数直到存在它可以有两个整除的数且[1,x,y,k]每两个数的差值均大于等于d。

这很容易实现,只需用一个小小的for循环。于是便有了我的第一个代码:

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
int arr[50010];
using namespace std;
int main()
{
	int t,d,j,num,ad,tip,k;//num为被整除数的数量
	cin >> t;
	for (int i=0; i < t; i++)
	{
		cin >> d;
		for (j = 6;; j++)
		{
			memset(arr, 0, sizeof(arr));
			num = 0;
			tip = 1;
			k = 1;
			while(k!=j+1)
			{
				if (j % k == 0)
				{
					arr[num] = k;
					num += 1;
				}
				k++;
			}
			if (num >= 4)
			{
				for (int l = 0; l < num - 1; l++)
				{
					if (arr[l + 1] - arr[l] < d)
					{
						tip = 0; break;
					}
				}
				if (tip == 0)
					continue;
				else
				{
					cout << j << endl;
					break;
				}
			}
 
		}
	}
}

 

  思路很好理解,从6开始一直向前寻找满足条件的最小k值,num为每一个k对应的被除数的数量。如果被除数的数量小于4,就不需要考虑,大于等于4时再去考虑被除数是否满足条件。

 


 

然鹅,理想很美好,全是TLE。

    该算法所需时间过长,无法满足题目所要求的时间限制。于是我就想利用本蒟蒻的线性筛先行处理。考虑的因素有以下几点:

  1. 首先满足要求的k一定是合数,因此,我可以使用线性筛先行把合数筛取到一个数组中,这样或许可以减少一些时间。
  2. 蒟蒻线性筛使用不熟练想练习一下。

然后就有了下面的代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define N  50010;//0~N
int arr[N];
bool prime[N];//若为质数值为1,否则为0
int num[N],dnum[N];//num存质数,dnum存合数
using namespace std;
int main()
{
    int count = 0, dcount = 0;//用来存以判断的质数和合数的个数
    memset(prime, 1, sizeof(prime));
    for (int i = 2; i < N; i++)
    {
        if (prime[i] == 1)
        {
            num[count++] = i;
        }
        else { dnum[dcount++] = i; }
        for (int j = 0; j < count && num[j] * i <= N; j++)
        {
            prime[num[j] * i] = 0;
            if (i % num[j] == 0)//直到num[j]为i的最小质因数
            {
                break;
            }
        }
    }
	int t,d,j,num,ad = 0,tip,k;
	cin >> t;
	for (int i=0; i < t; i++)
	{
		cin >> d;
		for (j=1;; j++)
		{
			memset(arr, 0, sizeof(arr));
			num = 0;
			tip = 1;
			k = 1;
			while(k<= dnum[j] /2)
			{
				if (dnum[j] % k == 0)
				{
					arr[num] = k;
					num += 1;
				}
				k++;
			}
			if (num >= 3)
			{
				for (int l = 0; l < num - 1; l++)
				{
					if (arr[l + 1] - arr[l] < d)
					{
						tip = 0; break;
					}
				}
				if (tip == 0)
					continue;
				else
				{
					cout << dnum[j] << endl;
					break;
				}
			}

		}
	}
	return 0;
}

 

  但是,想都不用想, 代码仍然超时。

     这样子看是思路8太对了哇......

     我寻思:

  1.  任何一个合数都可以分解为至少两个质数的乘积。
  2. k一定为合数。
  3. 若要使k最小,就需要使k只为两个质因数的乘积。

    这么说我只需要找到这两个质数就可以啦......(狂喜)

码来!

 

#include<cstdio>
#include<cstring>
const int N = 50010;
bool prime[N];
int  num[N];
using namespace std;
int main()
{
    int cnt = 0;
    int t, k;
    scanf("%d", &t);
    memset(prime, 1, sizeof(prime));
    for (int i = 2; i <= N; i++)
    {
        if (prime[i] == 0)  num[cnt++] = i;
        for (int j = 0; j < cnt && num[j] * i <= N; j++)
        {
            prime[num[j] * i] = 1;
            if (i % num[j] == 0) break;
        }
    }
    while (t--)
    {
        int d;
        scanf("%d", &d);
        int a, b;
        for (int i = 0; i < cnt; i++)
        {
            if (num[i] - 1 >= d)
            {
                a = num[i];
                k = i;
                break;
            }
        }
        for (int i = k + 1; i < cnt; i++)
        {
            if (num[i] - a >= d)
            {
                b = num[i];
                break;
            }
        }
        printf("%d\n", a * b);
    }
    return 0;
}

 

  最后,附上标准答案供dl参考(我是看不懂我菜)

 

#include <iostream>
#include <vector>
 
using namespace std;
 
void solve()
{
    int x;
    cin >> x;
    vector<int> p;
    for (int i = x + 1; ; i++)
    {
        int t = 1;
        for (int j = 2; j * j <= i; j++)
        {
            if (i % j == 0)
            {
                t = 0;
                break;
            }
        }
        if (t)
        {
            p.push_back(i);
            break;
        }
    }
    for (int i = p.back() + x; ; i++)
    {
        int t = 1;
        for (int j = 2; j * j <= i; j++)
        {
            if (i % j == 0)
            {
                t = 0;
                break;
            }
        }
        if (t)
        {
            p.push_back(i);
            break;
        }
    }
    cout << min(1ll * p[0] * p[1], 1ll * p[0] * p[0] * p[0]) << "\n";
}

 

  

 

 

 

 

标签:arr,696,int,CodeForces,++,num,Div.2,integer,include
来源: https://www.cnblogs.com/zzx6869/p/14336376.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有