关于CodeForces Round #696(Div.2)B题心得
作者:互联网
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 outputPositive 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
Input
- a has at least 4 divisors;
- difference between any two divisors of aa is at least d.
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).
OutputFor each test case print one integer a — the answer for this test case.
Example input2 1 2output6 15NoteIn 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,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。
该算法所需时间过长,无法满足题目所要求的时间限制。于是我就想利用本蒟蒻的线性筛先行处理。考虑的因素有以下几点:
- 首先满足要求的k一定是合数,因此,我可以使用线性筛先行把合数筛取到一个数组中,这样或许可以减少一些时间。
- 本蒟蒻线性筛使用不熟练想练习一下。
然后就有了下面的代码:
#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太对了哇......
我寻思:
- 任何一个合数都可以分解为至少两个质数的乘积。
- k一定为合数。
- 若要使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