https://codeforces.com/problemset/problem/576/A
题意:给定一个数x∈[1, n],然后猜测一个序列,我们可以在上交序列后,得知序列中的每个数y是否可以整除x,找出这个最短序列,可以让我们知道x是多少。
思路:这个序列中的数需要能够组合成任何[2,n]之间的数,这样我们对于任意的两个询问q1和q2,..qn,如果都能整除x,那么可能是q1q2..qn,如果有一个不能整除x,那么肯定不是x,所以我们需要预处理出所有的质因子,然后将单个质因子的幂组成的所有[1,n]的因子的集合列出来,就是ans。
总结:题目有两个关键点,第一个是意识到,我们给出的序列里的数,需要能够判定所有的[2,n]的可能的x,因为如果[2,n]中每个数都不满足x,那么答案是1,如果有数字能满足,那就在里面。
第二个点是,如何判定这个区间内的所有数?意识到每个数都能由若干个质因子相乘得到,先考虑质数,如果是质数,那么yes or no都可以在一次询问中得到。对于区间内的合数,判断它是否不是x,必须要先知道它的所有的质因子及其数量,再将质因子进行组合,就得到x了。。
有点抽象,就是假如有一个数t,我们判断它是不是我们要找的数,我们只要把x进行质因子分解,然后将相同的质因子进行相乘,得到若干个因子。然后我们询问这些因子能否整除x,如果有一个不能整除,那就寄。如果都能整除x,那答案就是t吗?不一定,假如t2在[1,n]区间内,还需要继续考虑后面的数字,因为x也可能是t2,t*2也满足t的所有质因子的条件。
这么看的话,正确的逻辑应该是,对[1,n]的每个数做质因子分解,然后记录每个质因子出现的最大次数,最后将这些质因子进行幂乘得到所有的因子集合..但是好像先线性筛所有的质因子,然后做幂成,不超过n的因子都要算进去,也是对的。
inline void solve() {primer.sievePrimes();auto primes = primer.getPrimesArray();int n;cin >> n;set<int> sett;for (const auto& p : primes) {if (p > n) {break;}long long cur = p;while (cur <= n) {sett.insert(cur);cur *= p;}}cout << sett.size() << "\n";for (auto v : sett) {cout << v << ' ';}
}