题目大意:有一个隐藏的长度为n的数组a,第i次读入的数为input[i],第i次询问输出x,返回a[input[i-1]+x%n],要求在1000次询问内得出n
1<=n<=1e6
思路:先输出333次1e6以内的随机数,维护得到的最大值ma,然后开始记录当前位置now,和每个数第一次出现的位置vis[input],输出333次1,输出1次ma,输出333次333,如果期间得到的是之前出现过的数,答案就是now-vis[input],可以认为此法得到答案的概率极大
原理待补
结论:2*根号(d)=N
d次+1,d次+d
2*d>N,就进行300-400次随机取值剩下的平分
//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
typedef long long ll;
ll vis[N];
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(false);
int now = 0;
ll op;
cin >> op;
ll ma = 0;
for (int i = 1; i <= 333; i++)
{
ll temp = 1 + rand() % 1000000;//在(1,1000000)范围内的随机数
cout << "+ " << temp << endl;
cout.flush();
cin >> op;
ma = max(ma, op);//找最大值
}
for (int i = 1; i <= 333; i++)
{
cout << "+ " << 1 << endl;
cout.flush();
now++;
cin >> op;
if (vis[op])
{
cout << "! " << now - vis[op] << endl;
cout.flush();
exit(0);
}
vis[op] = now;//找重复读入的数
}
cout << "+ " << ma << endl;
cout.flush();
now += ma;
cin >> op;
if (vis[op])
{
cout << "! " << now - vis[op] << endl;
cout.flush();
exit(0);
}
vis[op] = now;
for (int i = 1; i <= 333; i++)
{
cout << "+ " << 333 << endl;
cout.flush();
now+=333;
cin >> op;
if (vis[op])
{
cout << "! " << now - vis[op] << endl;
cout.flush();
exit(0);
}
vis[op] = now;
}
return 0;
}