题解:CF1355F Guess Divisors Count
首先是
在只考虑小质因子时的交互方式比较容易想到,取
这个询问策略本身不太能优化了,故考虑将
- 若
ans>2 ,根据我们刚刚的分析取2\cdot ans 作为答案就是正确的。 - 若
ans=2 ,由于>B 的数最多只能凑出3 个,此时能够达到的最大质因子个数为2^4=16 ,答案在[2,16] 中,直接取9 作为答案就行了。 - 若
ans=1 ,分析类似此时质因子最多有3 个,答案上界为8 ,直接输出8 即可。
只考虑
:::success[代码]
#include <bits/stdc++.h>
#define bint __int128
#define psb push_back
#define DEBUG 1
using namespace std;
typedef long long ll;
const ll LIM = 1e18, MAX=1e9;
const int M = 629;
int primes[M+5],tot; bool st[M+5];
void get_primes()
{
for (int i=2;i<=M;i++)
{
if (!st[i]) primes[++tot]=i;
for (int j=1;primes[j] <= M/i;j++)
{
st[i*primes[j]]=true;
if (i%primes[j]==0) break;
}
}
}
int getcnt(int x)
{
int res=1;
for (int i=2;i<=x/i;i++)
{
if (x%i==0)
{
int c=0;
while (x%i==0) x/=i, c++;
res=res*(c+1);
}
}
if (x>1) res=res*2;
return res;
}
ll X; int QCNT;
ll query(ll Q)
{
if (DEBUG) return QCNT++, __gcd(X,Q);
cout << "? " << Q << "\n"; fflush(stdout);
ll res; cin >> res; return res;
}
void solve()
{
if (DEBUG) cin >> X, QCNT=0, cout << "standard : " << getcnt(X) << "\n";
vector<int> pr;
for (int i=1;i<=tot;i++)
{
int j=i-1; ll prod=1;
while (j<tot && (bint)prod*primes[j+1] <= LIM) j++, prod*=primes[j];
//cout << i << " " << j << " " << prod << "\n";
ll res=query(prod); for (int k=i;k<=j;k++) if (res % primes[k] == 0) pr.psb(primes[k]);
i=j;
}
//for (int x : pr) cout << x << " "; cout << "\n";
int bound = MAX; ll cur = 1; int ans = 1;
for (int i=0;i<pr.size();i++)
{
if (pr[i] > bound) break;
ll prod=pr[i]; while (prod*pr[i] <= bound) prod*=pr[i];
//cout << pr[i] << " " << prod << "\n";
if ((bint)cur * prod > LIM) { ll res=query(cur); bound /= res; ans *= getcnt(res); cur=prod; }
else cur *= prod;
}
ans *= getcnt(query(cur));
if (ans==1) cout << "! 8\n";
else if (ans==2) cout << "! 9\n";
else cout << "! " << ans*2 << "\n";
fflush(stdout);
if (DEBUG) cout << "Query " << QCNT << "\n";
}
int main()
{
get_primes(); int T; cin >> T; while (T--) solve();
return 0;
}
:::