其他分享
首页 > 其他分享> > CF1406E Deleting Numbers 题解

CF1406E Deleting Numbers 题解

作者:互联网

Codeforces
Luogu

Description.

交互,初始有一个集合 \(S=\{1,2,\cdots,n\}\),你需要询问一个数 \(x\)。
你可以进行三种询问:

  1. 问有多少个数是 \(a\) 的倍数
  2. 问有多少个数是 \(a\) 的倍数,并把 \(a\) 倍数删除,\(x\) 无法被删除
  3. 回答你找到了 \(x\)。

\(n\le 10^5,\text{limit}\le 10000\)

Solution.

首先肯定大质数、小质数分别处理。
小质数肯定可以随便处理,因为总个数不超过 \(\mathcal O(\sqrt n)\)。
就直接先消,然后枚举指数。

主要是大质数怎么处理。
如果有小质数,那每个大质数 \(a\) 的倍数除了 \(a\) 和 \(x\) 其他都被消了。
所以可以 \(1\) 次判断是否存在 \(a|x\)
如果没有小质数,相当于答案是个质数,此时我们无法按照之前的方法判断。
有个朴素的想法是删一次问一次,这样是 \(O(2n)\) 的,无法通过。
考虑分块,对整块问一次,如果有再继续问,这样就变成 \(O(n+2\sqrt n)\) 了。

Coding.

点击查看代码
//Coded by Kamiyama_Shiki on 2021.11.15 {{{
//是啊……你就是那只鬼了……所以被你碰到以后,就轮到我变成鬼了
#include<bits/stdc++.h>
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}
template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
const int N=100005;int n;
const int V=N;int pr[V],pc,ls[V];char pv[V];//prinit{{{
inline void prinit(int n=V-1)
{
	pv[1]=1,ls[1]=0;for(int i=1;i<=n;i++)
	{
		if(!pv[i]) pr[++pc]=i,ls[i]=i;
		for(int j=1;j<=pc&&i*pr[j]<=n;j++) {pv[i*pr[j]]=1;if(i%pr[j]==0) break;}
	}
}//}}}
inline int A(int x)
{
	if(x>n) return 0;
	printf("A %d\n",x),fflush(stdout);
	int w;return read(w),w;
}
inline int B(int x)
{
	if(x>n) return 0;
	printf("B %d\n",x),fflush(stdout);
	int w;return read(w),w;
}
inline void C(int x) {printf("C %d\n",x),fflush(stdout);}
int main()
{
	int rs=1,wh=1;read(n),prinit(n);
	for(int i=1;i<=pc&&pr[i]*pr[i]<=n;i++)
	{
		int x=pr[i],nw=0;B(pr[i]),nw=A(pr[i]);
		wh=i+1;while(nw) rs*=pr[i],nw=A(x*=pr[i]);
	}
	if(rs!=1)
	{
		for(int i=wh;i<=pc;i++) if(A(pr[i])>1) return C(pr[i]*rs),0;
		return C(rs),0;
	}
	for(int l=wh,r=l+99,now=A(1),nx;l<=pc;l+=100,r+=100,now=nx)
	{
		for(int i=l;i<=r&&i<=pc;i++) B(pr[i]);
		nx=A(1);if(now==nx+min(r,pc)-l+1) continue;
		for(int i=l;i<=r&&i<=pc;i++) if(A(pr[i])) return C(pr[i]),0;
	}return C(1),0;
}

标签:return,rs,int,题解,质数,CF1406E,read,Deleting,void
来源: https://www.cnblogs.com/pealfrog/p/15559418.html