codeforces1114e(交互题,随机数的锅)

题目链接:传送门

题意:有一串长度为n(2<=n<=1e6)的等差数列,每个数都为小于等于1e9的非负数,且打乱了,现在你有60次询问的机会,询问有两种形式:

1. >  x  查询数组中是否含有大于x的数存在

2.? x  查询数组下标为x的数值

求出等差数列的差和最小值。

思路:比较清晰的,可以在30次里二分求出最大值,接下来应该就是随机取几个数来通过差gcd求d,最后可以求得最小值。

问题在于rand()随机的伪随机数比较差,效果不好。看了别人博客后发现了mt19937,没有深究,但是应该会比rand()好一些。

用法:

#include <iostream>
#include <random>
 
using namespace std;
 
int main()
{
    mt19937 mt_rand(time(0));
 
    cout << mt_rand() << endl;
 
    return 0;
}

题目代码:

#include<bits/stdc++.h>
#include <random>
using namespace std;
int tim;
map<int,int>mp;
bool check(int x)
{
    tim--;
    cout<<"> "<<x<<endl;
    int ans;
    cin>>ans;
    if(ans)return 1;
    else return 0;
}

int gcd(int a,int b)
{
    int r;
    while(b>0)
    {
        r=a%b;
        a=b;
        b=r;
    }
    return a;
}
int ak[105];
int main()
{
    mt19937 mt_rand(time(0));
    mp.clear();
    tim = 60;
    int n;
    cin>>n;
    int l = 0,r =1000000000;
    int ans;
    while (l <= r)
    {
        int mid = (l + r)/2;
        if(check(mid)) ans=mid,l = mid+1;
        else r = mid-1;
    }
    ans++;
//    cout << ans <<endl;
    int cnt = 0;
    while(tim--)
    {
        int p= mt_rand()%n +1;
        int tt = 0 ;
        while(mp[p]&&tt<1000000){
            tt++;
            p = mt_rand()%n +1;
        }
        mp[p] = 1;
        cout<<"? "<<p<<endl;
        cin>>ak[cnt];
        cnt++;
        if(cnt>=n)break;
    }
    sort(ak,ak+cnt);
    for(int i = 0;i<cnt-1;i++){
        ak[i]=  ak[i+1] - ak[i];
    }
    sort(ak,ak+cnt-1);
    int an = ak[0];
    for(int i =1;i<cnt-1;i++){
        an = gcd(ak[i],an);
    }
    cout<<"! "<<ans - (n-1) * an<<" "<<an<<endl;     
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值