#L4138. 「PA 2024」Dzielniki

「PA 2024」Dzielniki

题目描述

我们从区间 [1,n][1, n] 中选取了一个整数 xx,你的任务是猜这些数。你不必盲目地猜,可以问一些问题。每个问题你可以询问区间 [0,c][0, c] 中的某个整数 yy,我们会告诉你 x+yx + y 的因子个数。

为了让题目稍微困难一些,你需要在一次运行中解决 tt 个用例。询问总数被限制在 qq 次。

使用交互库交互

请注意:由于 LibreOJ 的实现与 PA 中所用 OJ 不同,因此这部分交互方式与原题有一些区别。

在程序的开头你应该使用 #include "dzilib.h" 引入交互库。

你需要实现如下函数来完成本题。

void Solve():程序只会调用此函数一次,在这个函数中,你需要实现猜测 tt 个用例的所有程序逻辑。 你可以调用如下函数。

int GetT():返回 tt 的值。 long long GetN():返回 nn 的值。 int GetQ():返回 qq 的值。 long long GetC():返回 cc 的值。 int Ask(long long y):返回要猜的数 xxyy 的和的因子个数。你需要保证 0yc0 \le y \le c。 void Answer(long long x):做出一次回答。此函数无返回值。 如果你调用 Ask() 函数的总次数超过 qq,则你的程序会被判为 Wrong Answer。如果存在一次调用 Answer() 函数,你猜测的数与答案不同,你的程序也会被判为 Wrong Answer。

使用 I/O 交互

与 PA 题目不同的是,在 LibreOJ 上,你可以使用标准输入输出与交互库交互。

首先你需要从标准输入中读取四个整数 t,n,q,ct, n, q, c,意义如题目描述。

接下来开始交互过程。

如果想要做出一次询问,则按 ? y 的格式向标准输出写入一行,其中 yy 代表你的查询。接着你需要从标准输入中读取一个整数,表示交互库做出的回答。 如果想要做出一次回答,则按 ! x 的格式向标准输出写入一行,其中 xx 代表你的回答。接着你需要从标准输入中读取一个整数,如果这个整数为 00,则表示你的回答错误,你需要立刻停止你的程序,否则这个整数将为 11,请忽略这个整数,继续下一组数据的交互。 当所有 tt 组数据交互结束时,你需要立刻停止你的程序。

交互库

所有测试点中的 xx 和它们的顺序都是预先确定好的。这意味着交互库行为不会根据你的程序行为而进行调整。

样例交互

样例中 t=2,n=106,q=104,c=1015t=2, n=10^6, q=10^4, c=10^{15},要猜的数分别为 1000100011

函数调用 返回值 注释
GetT() 22 t=2t=2
GetN() 10000001000000 n=106n=10^6
GetQ() 1000010000 q=104q=10^4
GetC() 10000000000000001000000000000000 c=1015c=10^15
Ask(1) 88 x+18个因子:17111377911431001x+1有8个因子:1,7,11,13,77,91,143和1001
Ask(24) 1111 x+2411个因子:12481632641285121024x+24有11个因子:1,2,4,8,16,32,64,128,512和1024
Answer(1000) - 回答正确,开始下一组数据的交互
GetT() 22 允许询问,并且返回值不变
Answer(1) - 正确的交互样例,并给出最后一个测试用例的正确答案。一旦给出答案,程序就应终止。

交互过程中提出了 2 次询问,未超出 10, 000 次询问的限制。请记住,一组数据中所有测试点的总查询次数才是最重要的。

数据范围与提示

详细子任务限制如下表所示。在一个子任务中,t,n,q,ct,n,q,c 的值都相同。

子任务编号 tt nn qq cc
1 50 10510^5 50000 101210^{12}
2 10610^6 5000
3 10910^9 50000
4 10 5000 101710^{17}
5 2000
6 1300
7 101410^{14} 950
8 820
9 750
10 720

样例不属于任何子任务,可以在样例错误的情况下得分。