「杂题乱刷2」AT_arc184_a
题目链接
解题思路
Q = 999:
我们考虑将第一个硬币与其余的硬币作比较,最后若交互库返回的 \(1\) 更多,那么说明第 \(1\) 枚硬币是假币,否则第 \(1\) 枚硬币是真币,直接存动态数组最后输出即可。
操作次数容易得出为 \(999\) 次。
Q = 919:
考虑将每 \(11\) 枚硬币分一个组,每次询问每组的第一个硬币和剩下的硬币,由于假币数量只有 \(10\) 枚,因此如果所有硬币都相同,那么这一堆硬币必定全是真币,否则,这一堆硬币中必有假币。
这样分,我们会分成 \(90\) 组硬币和剩下的 \(10\) 枚硬币,由于假币的数量只有 \(10\) 个,因此这 \(90\) 组硬币中至少会有 \(80\) 组全为真币,而根据前文提到的如果所有硬币都相同,那么这一堆硬币必定全是真币,我们必定可以确定出一个真币的位置,我们可以通过将这枚真币与最后 \(10\) 枚硬币比较来确定最后 \(10\) 枚硬币的真伪情况。随后我们可以再通过将这枚真币与必定有假币的硬币堆中的一个硬币比较,每次比较,我们就可以确定这堆硬币中的硬币真伪情况。
综上,我们可以通过这种方式找出所有硬币。
如果 \(10\) 枚假币都在前面分的堆中,则操作次数为 \(10 \times 90 + 10 = 910\) 次。
、
否则,操作次数为 \(10 \times 90 + 9 + 10 = 919\) 次。
综上,操作次数最大为 \(919\) 次。
参考代码
/*
time:2024/9/22
contest : https://codeforces.com/contest/877
Tips:
你数组开小了吗?
你 MLE 了吗?
你觉得是贪心,是不是该想想 dp?
一个小时没调出来,是不是该考虑换题?
打 cf 不要用 umap!!!
记住,rating 是身外之物。
该冲正解时冲正解!
Problem:
如果你会:
取模取了吗?
算法对拍了吗?
有没有保留小数据的暴力?
有没有清空?
精度够吗?
时间复杂度真的正确嘛?
会不会炸空间?
最大数据会不会炸?
自己造数据!
如果你不会:
有没有想最低分的dp? dp 也是一种暴力
会不会写暴力分?
暴力能否优化?
暴力打表看看有没有非常明显的规律,有的黑题的规律就是cout<<N*N;
能否分块暴力?
有没有想最低分的dp?
那个dp能否优化?
不要往深的地方思考,想浅一点多想点
冷静冷静再冷静!
对拍对拍再对拍!
思路:
*/
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define pii pair<ll,ll>
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
//#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) (1ll*(x)/__gcd(x,y)*(y))
#define Sum(x,y) (1ll*((x)+(y))*((y)-(x)+1)/2)
#define x first
#define y second
#define aty cout<<"Yes\n";
#define atn cout<<"No\n";
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
#define xxy cout<<"yes\n";
#define xxn cout<<"no\n";
#define printcf(x) x?cout<<"YES\n":cout<<"NO\n";
#define printat(x) x?cout<<"Yes\n":cout<<"No\n";
#define printxx(x) x?cout<<"yes\n":cout<<"no\n";
#define maxqueue priority_queue<ll>
#define minqueue priority_queue<ll,vector<ll>,greater<ll>>
#define bug cout<<"---------------------------------------\n";
//ll pw(ll x,ll y,ll mod){if(x==0)return 0;ll an=1,tmp=x;while(y){if(y&1)an=(an*tmp)%mod;tmp=(tmp*tmp)%mod;y>>=1;}return an;}
template<typename T1,typename T2>bool Max(T1&x,T2 y){if(y>x)return x=y,1;return 0;}
template<typename T1,typename T2>bool Min(T1&x,T2 y){if(y<x)return x=y,1;return 0;}
ll _t_;
void _clear(){}
map<ll,map<ll,ll>>mp;
ll real_ans[1010];
ll spjsum;
bool f(ll x,ll y)
{
spjsum++;
if(spjsum>950)
{
cout<<"The ans is too long!\n";
exit(-1);
}
return real_ans[x]!=real_ans[y];
}
ll ask(ll x,ll y)
{
if(x<1 || y<1 || x>1000 || y>1000)
exit(-1);
if(mp[x][y])
return mp[x][y]-2;
cout<<"? "<<x<<' '<<y<<endl;
ll z;
cin>>z;
mp[x][y]=z+2;
if(z==-1)
exit(-1);
return z;
}
ll bl[100010];
ll K;
ll _real;
vector<ll>ans;
vector<ll>G[100010][2];
void solve()
{
// forl(i,996,1000)
// real_ans[i]=1;
// forl(i,1,5)
// real_ans[i]=1;
_clear();
ll x;
cin>>x>>x>>x;
forll(i,1,990,11)
{
K++;
G[K][1].pb(i);
forl(j,i+1,i+10)
{
if(!ask(i,j))
G[K][1].pb(j);
else
G[K][0].pb(j),
bl[K]=1;
}
if(!bl[K])
_real=i;
}
forl(i,991,1000)
if(ask(i,_real))
ans.pb(i);
K=0;
forll(i,1,990,11)
if(bl[++K])
{
if(ask(_real,G[K][1][0]))
for(auto i:G[K][1])
ans.pb(i);
else
for(auto i:G[K][0])
ans.pb(i);
}
sort(ans.begin(),ans.end());
cout<<"! ";
for(auto i:ans)
cout<<i<<' ';
cout<<endl;
}
int main()
{
// freopen("tst.txt","r",stdin);
// freopen("sans.txt","w",stdout);
// IOS;
_t_=1;
// cin>>_t_;
while(_t_--)
solve();
QwQ;
}