【题目】
题目传送门Primal Sport
题目描述:
Alice 和 Bob 又在玩一个游戏。他们从一个数字 开始( ≥ 3),期望到很大的数字。游戏是这样的:
Alice 先走,然后轮流。在第 i 个回合中,轮到的玩家找一个小于当前数字的素数,然后选择大于当前数字且是找的素数的倍数的最小数。即选择的素数 < , ≥ , 是 的倍数,注意如果 是 的约数,那么数字不会变。
L 知道了他们两轮后的状态,现在给你一个 表示两轮后选择的数字,请你确定最小的起始数字 。特别提醒,玩家不一定每一步选择是最聪明的,你应该考虑所有可能的情况。
输入格式:
输入一个整数 ,保证 是合数
输出格式:
输出一个整数
样例数据:
输入
14输出
6
输入
20输出
15
备注:
样例数据1解释:
= 6
第一轮:Alice选择素数 5,并决定这轮数字 = 10
第一轮:Bob选择素数 7,并决定这轮数字 = 14
样例数据2解释:
= 15
第一轮:Alice选择素数 2,并决定这轮数字 = 16
第一轮:Bob选择素数 5,并决定这轮数字 = 20
数据规模与约定:
20%数据, ≤ 20
40%数据, ≤ 2000
100%数据,4 ≤ ≤ 1000000
【知识储备】
-
素数的最大质因数为它本身
-
合数的最大质因数等于它最大因数(除去它本身)的最大质因数
另外还有线性筛素数和最大质因数(可以去代码里看)
【分析】
这是一道有关数学的题,起初看到题的时候还读不懂,不过蒟蒻最后还是暴力拿了80分
其实我的代码超时主要超在每次算最大质因数时我用的是枚举,而标程上是用的线性筛法
先讲一讲如何思考这道题吧
由于题目给出的是 ,我们就从 推到 再推到
我们用 表示 的质因数,用 表示 的质因数(题目要求 是质数且 是 的因数)
那么根据题意,易知, < ≤ ,又根据 是大于 的 倍数的最小数,我们可以得出 - < ≤
推 时也是一样的思路,即 - < ≤
由于我们要求的是 的最小值,那 、 越大,答案越小,所以 、 取 、 的最大质因数
那么最后的 = - , ≥ - , 不能直接取 - ,根据样例分析一下就知道了
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1000000;
const int oo=2e+9;
int p[N],prime[N];
bool mark[N];
void init(int x)
{
int i,j,sum=0;
memset(mark,true,sizeof(mark));
mark[1]=false;
for(i=2;i<=x;++i)
{
if(mark[i])
{
p[i]=i;
prime[++sum]=i;
}
for(j=1;j<=sum&&i*prime[j]<=x;++j)
{
p[i*prime[j]]=p[i];
mark[i*prime[j]]=false;
if(i%prime[j]==0) break;
}
}
}
int main()
{
// freopen("game.in","r",stdin);
// freopen("game.out","w",stdout);
int x0,x1,x2;
scanf("%d",&x2);
init(x2);
x0=oo;
for(x1=x2-p[x2]+1;x1<=x2;++x1)
if(!mark[x1])
x0=min(x0,x1-p[x1]+1);
printf("%d",x0);
// fclose(stdin);
// fclose(stdout);
return 0;
}