题目链接:Primal Sport
题意
和 两人在玩一个游戏, 先开始,两人轮流进行,第 次游戏中,对于一个整数 ,选择一个素数 ,然后找到一个最小的整数 ,使得 且 能被 整除,将这个数字作为下一次游戏的新值 继续进行游戏,现在游戏已经进行了两次,得到了 的值,问最小的可能的 的值为多少。
输入
输入为一个整数 ,数据保证 是合数。
输出
输出最小的可能的 的值。
样例
输入 |
---|
14 |
输出 |
6 |
提示 |
设
,则其中一种合法的游戏过程如下: 1. 选择 , 的值为 ; 2. 选择 , 的值为 。 |
输入 |
---|
20 |
输出 |
15 |
提示 |
设
,则其中一种合法的游戏过程如下: 1. 选择 , 的值为 ; 2. 选择 , 的值为 。 |
输入 |
---|
8192 |
输出 |
8191 |
题解
我们可以根据 的值确定 的合法的取值区间: ,其中 为 的最大的质因子,对于 的值,只要选择质数 就可以通过 得到 的值,对于 的值,如果选择质数 ,则只能得到 的值,如果选择其他质数,由于 是最大的质因数,选择其他质数能够改变的增量一定小于 ,所以 。但是最小的 并不能得到最小的 ,因此对于 我们需要枚举所有可能的 的值,来找到最小的 的值。
过题代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
#define LL long long
const int maxn = 1000000 + 100;
int cnt, n;
bool vis[maxn];
int prime[maxn];
void Prime() {
for(int i = 2; i < maxn; ++i) {
if(!vis[i]) {
prime[cnt++] = i;
}
for(int j = 0; j < cnt && i < maxn / prime[j]; ++j) {
int k = i * prime[j];
vis[k] = true;
if(i % prime[j] == 0) {
break;
}
}
}
}
int Find(int x) {
int ret;
int xx = x;
for(int i = 0; i < cnt && prime[i] <= xx / prime[i]; ++i) {
while(x % prime[i] == 0) {
x /= prime[i];
ret = prime[i];
}
}
if(x != 1) {
ret = x;
}
return ret;
}
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false);
Prime();
while(scanf("%d", &n) != EOF) {
int Start = Find(n);
int ans = INT_MAX;
for(int i = n - Start + 1; i <= n; ++i) {
int tmp = i - Find(i) + 1;
if(tmp >= 3) {
ans = min(ans, tmp);
}
}
printf("%d\n", ans);
}
return 0;
}