Codeforces 1406E - Deleting Numbers(根分+数论)
一道个人感觉挺有意思的交互题,本人一开始想了个奇奇怪怪的做法,还以为卡不进去,结果发现竟然过了,而且还是正解(
首先看到这类题目可以考虑每次删掉一个质数的倍数,即对某个 \(pr_i\) 执行 B 操作,然后对 \(pr_i\) 进行 A 询问,根据询问得到的值是否等于理论上删去这些数后 \(pr_i\) 的倍数个数来判断 \(pr_i\) 是否是 \(x\) 的因数,如果是那么就枚举 \(pr_i\) 的 \(2,3,4,\cdots\) 次方,再对这些次方执行 A 询问,以此来判断 \(x\) 质因数分解式中 \(pr_i\) 的次数。
算下询问次数,询问 \(pr_i\) 的 \(2,3,4,\cdots\) 的次数显然与 \(x\) 质因数分解式中 \(x\) 每个质因数的次数之和有关,是 \(\log\) 级别的,最多只有 \(20\) 可以忽略,瓶颈在于每个质因数都要进行两次操作,打表可以发现 \(10^5\) 以内质因数个数刚好比 \(10^4\) 小个几百,因此 \(2\pi(n)\) 是 \(2\times 10^4\) 级别的,过不去。
考虑优化,很明显对于 B 操作而言,我们是可以在操作的同时问出 \(x\) 的倍数的,而刚刚的解法中并没有利用这个性质,因此考虑从这个性质入手解题,我们还是从小到大枚举质因子,只不过与刚才不同的一点是,我们不每进行一次 B 询问都跟一个 A 询问,我们只做 B 询问,那么对于大多数质数,每次 B 询问时也可以根据结果知道该质数是否是 \(x\) 的因子,只有一个例外——那就是 \(x\) 的最小质因子,因此接下来我们只用找到 \(x\) 的最小质因子及它的次数即可,这也是本题的难点所在,我就在这个地方卡了 20+min 后想到了这个解法。
注意到 A 操作起始下标是可以从 \(1\) 开始的,而通过 \(A\ 1\) 我们则可以知道刚才询问的数中是否出现了 \(x\) 的质因子,因此我们考虑根分,每 100 次 B 询问来一次 A 1,那么我们可以把质因子按大小分为 \(\lceil\dfrac{\pi(n)}{100}\rceil\),显然最小质因子就在最后一个 A 1 等于剩余数个数与第一个 A 1 不等于剩余数个数的位置之间,中间部分就暴力枚举质因子然后用 A 质因子判断即可,这样总操作次数为 \(\pi(n)+100+\lceil\dfrac{\pi(n)}{100}\rceil+\log n\),实测询问次数最多 9700+ 次,刚好卡过。
const int MAXN=1e5;
int n,pr[MAXN/5+5],prcnt=0;
bool vis[MAXN+5],is[MAXN+5],has[MAXN+5];
vector<int> fac[MAXN+5];
int cnt[MAXN+5];
void sieve(){
for(int i=2;i<=n;i++){
if(!vis[i]) pr[++prcnt]=i;
for(int j=1;j<=prcnt&&pr[j]*i<=n;j++){
vis[pr[j]*i]=1;
if(i%pr[j]==0) break;
}
}
for(int i=1;i<=n;i++) cnt[i]=n/i;
for(int i=1;i<=prcnt;i++) for(ll j=pr[i];j<=n;j*=pr[i]) is[j]=1;
for(int i=1;i<=n;i++) for(int j=i;j<=n;j+=i) fac[j].pb(i);
}
void del(int x){for(int y:fac[x]) cnt[y]--;has[x]=1;}
void del_mul(int x){for(int i=x;i<=n;i+=x) if(!has[i]) del(i);}
int qr1(int x){printf("A %d\n",x);fflush(stdout);int res;scanf("%d",&res);return res;}
int qr2(int x){printf("B %d\n",x);fflush(stdout);int res;scanf("%d",&res);return res;}
int main(){
scanf("%d",&n);sieve();
int cur=1,mn=prcnt,cc=0,fst_blk=0;
for(int i=1;i<=prcnt;i++){
int t=qr2(pr[i]);
if(t!=cnt[pr[i]]){
if(cur==1) mn=i;del_mul(pr[i]);
cur*=pr[i];
for(ll x=1ll*pr[i]*pr[i];x<=n;x*=pr[i]){
int num=qr1(x);//printf("%d %d\n",x,cnt[x]);
if(num==cnt[x]) break;cur*=pr[i];
}
} else del_mul(pr[i]);
++cc;
if(cc==100&&!fst_blk){
cc=0;int x=qr1(1);
if(x!=cnt[1]) fst_blk=i;
}
} if(!fst_blk){int x=qr1(1);if(x!=cnt[1]) fst_blk=prcnt;}
for(int j=(fst_blk-1)/100*100+1;j<=min(fst_blk,mn);j++){
int x=qr1(pr[j]);
if(x!=cnt[pr[j]]){
cur*=pr[j];
for(ll k=1ll*pr[j]*pr[j];k<=n;k*=pr[j]){
int num=qr1(k);//printf("%d %d\n",x,cnt[x]);
if(num==cnt[k]) break;cur*=pr[j];
} break;
}
}
printf("C %d\n",cur);fflush(stdout);
return 0;
}
Codeforces 1406E - Deleting Numbers(根分+数论)的更多相关文章
- Codeforces - 55D Beautiful numbers (数位dp+数论)
题意:求[L,R](1<=L<=R<=9e18)区间中所有能被自己数位上的非零数整除的数的个数 分析:丛数据量可以分析出是用数位dp求解,区间个数可以转化为sum(R)-sum(L- ...
- Codeforces 1446D2 - Frequency Problem (Hard Version)(根分)
Codeforces 题面传送门 & 洛谷题面传送门 人菜结论题做不动/kk 首先考虑此题一个非常关键的结论:我们设整个数列的众数为 \(G\),那么在最优子段中,\(G\) 一定是该子段的众 ...
- CodeForces 55D "Beautiful numbers"(数位DP+离散化处理)
传送门 参考资料: [1]:CodeForces 55D Beautiful numbers(数位dp&&离散化) 我的理解: 起初,我先定义一个三维数组 dp[ i ][ j ][ ...
- Codeforces 878 E. Numbers on the blackboard
Codeforces 878 E. Numbers on the blackboard 解题思路 有一种最优策略是每次选择最后面一个大于等于 \(0\) 的元素进行合并,这样做完以后相当于给这个元素乘 ...
- PAT 甲级 1069 The Black Hole of Numbers (20 分)(内含别人string处理的精简代码)
1069 The Black Hole of Numbers (20 分) For any 4-digit integer except the ones with all the digits ...
- PAT 甲级 1023 Have Fun with Numbers (20 分)(permutation是全排列题目没读懂)
1023 Have Fun with Numbers (20 分) Notice that the number 123456789 is a 9-digit number consisting ...
- Codeforces 55D. Beautiful numbers(数位DP,离散化)
Codeforces 55D. Beautiful numbers 题意 求[L,R]区间内有多少个数满足:该数能被其每一位数字都整除(如12,24,15等). 思路 一开始以为是数位DP的水题,觉得 ...
- 1069 The Black Hole of Numbers (20分)
1069 The Black Hole of Numbers (20分) 1. 题目 2. 思路 把输入的数字作为字符串,调用排序算法,求最大最小 3. 注意点 输入的数字的范围是(0, 104), ...
- 1023 Have Fun with Numbers (20 分)
1023 Have Fun with Numbers (20 分) Notice that the number 123456789 is a 9-digit number consisting ...
随机推荐
- JavaScript03
类型转换和运算符 typeof函数 检测数据类型,可以使用以下两种调用的方式: typeof 变量或表达式 typeof(变量或表达式) var n="asda"; console ...
- UltraSoft - Beta - Scrum Meeting 5
Date: May 21st, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 修复了课程通知链接的bug Liuzh 前端 暂无 Kkkk 前端 增加消息中心板 ...
- Noip模拟37 2021.8.12
T1 数列 真是考场上不是数学的乱推柿子,想定理,是数学的没想出来.. 比较悲伤... 列柿子不用动脑子,就是没有想出来$EXgcd$解不定方程,淦.. 解处一组解后利用比较显然的性质: $x+\fr ...
- 如何用PADS进行PCB设计?这6步就够了
在使用PADS进行PCB设计的过程中,需要对印制板的设计流程以及相关的注意事项进行重点关注,这样才能更好的为工作组中的设计人员提供系统的设计规范,同时也方便设计人员之间进行相互的交流和检查. 02 设 ...
- Spring Security:简单的保护一个SpringBoot应用程序(总结)
Spring Security 在 Java类中的配置 在 Spring Security 中使用 Java配置,可以轻松配置 Spring Security 而无需使用 XML . 在Spring ...
- Makefile目标文件搜索(VPATH和vpath
转载:http://c.biancheng.net/view/7051.html 我们都知道一个工程文件中的源文件有很多,并且存放的位置可能不相同(工程中的文件会被放到不同的目录下),所以按照之前的方 ...
- 最大连续数列和 牛客网 程序员面试金典 C++ Python
最大连续数列和 牛客网 程序员面试金典 C++ Python 题目描述 对于一个有正有负的整数数组,请找出总和最大的连续数列. 给定一个int数组A和数组大小n,请返回最大的连续数列的和.保证n的大小 ...
- POJ 1274 The Perfect Stall(二分图最大匹配)
题意: N头牛M个牛棚,每只牛都有它自己指定的若干个它愿意呆的牛棚. 每个牛棚最多呆一头牛. 问最多可以满足多少头牛的愿望. 思路: 裸二分图最大匹配. 代码: int n,m; vector< ...
- oracle 定时任务增、删、改、查
增: 创建一个计划任务 begin sys.dbms_job.submit(job=>:job, what=>'要定时执行的存储过程名:',--例如:包名.存储过程名; 记得写分号 ne ...
- p->next = q, p = q->next, q->next = p->next的区别