「DROI」Round 1 游戏 题解
Demeanor_Roy · · 题解
- 出题人题解。
首先发觉
令
-
考虑质数
p ,令k 是使p^k \leq n 的最大正整数,显然若所选x 中p 的指数为k ,则必须存在一个a_i 使得a_i 中p 的指数等于k 才能唯一确定x 中p 的指数。所以若存在一个质数p ,使得所有a_i 中p 指数的最大值小于k ,那么我们就可以选择p^k 作为x ,小朋友必败。 -
而对于任意两个不同质数
p ,q ,显然都有p^{k1} \times q^{k2} > n ,所以一个a_i 最多能使小朋友确定x 中一个质数的指数。据此可知,Q 次提问最多能确定Q 个质数的指数。显然当\pi(n) > Q 时,小朋友必然无法猜出x 的值,直接输出game won't stop即可。
于是我们接下来只需要考虑
先给出结论:当且仅当对于所有质数
-
充分性:根据以上条件,小朋友一定能确定每个质数在
x 中的指数,故能唯一确定x 。 -
必要性:设质数
p 不满足上述条件,不妨令x=p^k ,则小朋友无法唯一确定x 。
于是对于所有质数
这里顺便阐明一下部分分依据:
-
第一档部分分是给
n^2Q 暴力的,只要稍加思考过这档不难。 -
第二档部分分是给没有推出缩小
n 的范围但发掘了一些其他性质的。 -
第三档部分分是给所有性质都推出来,但不会线性筛或者常数实在太大的人。
至此本题解决完毕。下附代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=3.3e7+10,M=2e6+10;
LL n,A[M];
int T,m,id,v[N],sum[N],prime[M<<1];
bool ispk[N],check[N];
inline LL read()
{
LL x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
}
inline void Euler()
{
v[1]=ispk[1]=true;
for(int i=2;i<N;i++)
{
if(!v[i]) v[i]=i,prime[++id]=i,ispk[i]=true;
for(int j=1;j<=id;j++)
{
if(i*prime[j]>=N||v[i]<prime[j]) break;
v[i*prime[j]]=prime[j];
ispk[i*prime[j]]=(ispk[i]&&(v[i]==prime[j]));
}
sum[i]=sum[i-1]+(v[i]==i);
}
}
inline void solve()
{
n=read(),m=read();
for(int i=1;i<=m;i++) A[i]=read();
if(prime[m+1]<=n) return printf("game won't stop\n"),void();
for(int i=1;i<=m;i++) check[prime[i]]=false;
int now=0;
for(int i=1;i<=m;i++)
{
while(A[i]*A[i]>n&&!ispk[A[i]]) A[i]/=v[A[i]];
if(A[i]*v[A[i]]>n)
{
now+=!check[v[A[i]]];
check[v[A[i]]]=true;
}
if(now==sum[n])
{
printf("%d\n",i);
break;
}
else if(m-i+now<sum[n])
{
printf("game won't stop\n");
break;
}
}
}
int main()
{
Euler();
scanf("%d",&T);
while(T--) solve();
return 0;
}