Codeforces 1114E(数学+随机算法)

题面

传送门

分析

通过二分答案,我们显然可以求出数组中最大的数,即等差数列的末项

接着随机取一些数组中的数,对他们两两做差,把得到的差取gcd即为公差

例a={1,5,9,13},我们随机取了1 9 13,两两的差为8,4,12,取gcd为4

已知末项和公差即可求出首项

可以证明错误的概率< \(1.86185\times10?^{-9}\)

具体证明我也不懂,可以看cf官方题解,需要用到莫比乌斯反演

注意生成随机数时不能直接用rand(),因为rand()的返回值<32768,而n很可能>32768,需要用rand()*rand()再%n

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int n;
int ask1(int x){
    printf("? %d\n",x);
    fflush(stdout);
    int ans=0;
    scanf("%d",&ans);
    return ans;
}
int ask2(int x){
    printf("> %d\n",x);
    fflush(stdout);
    int ans=0;
    scanf("%d",&ans);
    return ans;
} 

int asks=0;
int bin_search(int l,int r){
    int ans=0;
    while(l<=r){
        int mid=(l+r)>>1;
        asks++;
        if(ask2(mid)){
            l=mid+1;
        }else{
            ans=mid;
            r=mid-1;
        }
    }
    return ans;
}

int a[62];
inline int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}
inline int random(){
    return (long long)rand()*rand()%n+1;
}
int main(){
    srand(19260817);
    scanf("%d",&n);
    fflush(stdout);
    int x=bin_search(0,1e9+1);
//  printf("debug:%d\n",x);
    for(int i=1;i<=60-asks;i++){
        a[i]=ask1(random());
    }
    int ans=0;
    for(int i=1;i<=60-asks;i++){
        for(int j=i+1;j<=60-asks;j++){
            ans=gcd(ans,abs(a[i]-a[j]));
        }
    }
    printf("! %d %d\n",x-ans*(n-1),ans);
}

原文地址:https://www.cnblogs.com/birchtree/p/10360859.html

时间: 2024-10-09 09:19:36

Codeforces 1114E(数学+随机算法)的相关文章

由抽奖软件想到的随机算法总结

整整三年没更新博客了,今天和女友聊天,聊到了博客,就回来看看. 最近接触到抽奖软件,下载的源码是http://download.csdn.net/detail/ghz_sd/6918125,在这里为开源软件作出贡献的人致敬,这个软件的作者a米山,是个非常好的人,耐心的帮我调试,他的算法很简单,就是纯粹的random,用的rand()函数,我给他提了个需求,写一个作弊类,实现的功能是:指定人的中奖概率提高,配置文件类似于这样: <xml> <win> <name='a' pro

中科院随机算法课程(孙晓明主讲)topic list

如题,列出<随机算法>课程的topic list,以记录和供有兴趣的朋友研究. Lession1:生日悖论.生日攻击.两个常用数学工具(马尔科夫不等式.切比雪夫不等式) Lession2:radom quick sort(hw).矩阵乘法判定.min(max())=max(min()).复杂性类(BPP/RP/CORP/ZPP) Lession3:证明BPP2/3=BPP0.99.ZPP<=RP^CORP.Game Tree Lession4:Balls and Bins Lession

随机算法

随机算法听起来就很不靠谱...但是有的时候还是很有用的,而且也有正解就是随机化的题目. 要说定义好像也没什么好讲的,要不先看道题吧. 偷上网:https://www.luogu.org/problemnew/show/P4703 luogu某次月赛题,当时刚开始看这个题网站就崩溃了,于是也没有怎么想,今天再想还是没有什么思路. 一开始想到在边上找,又觉得在中间的可能性也很大,所以似乎并没有什么规律.看了题解发现这道题可以用随机化...随机生成一些点,check一下是否满足条件,这样多找几次总能找

Miller_Rabin算法(随机算法,判断一个数是否是素数)

1 const int S = 20;//随机算法判定次数,S越大,判错概率越小 2 LL pow_mod(LL a, LL b, LL mod) { // a^b%mod 3 LL ans = 1; 4 a = a % mod; 5 while(b) { 6 if(b & 1) { 7 ans = (ans * a) % mod; 8 } 9 a = ( a * a ) % mod; 10 b >>= 1; 11 } 12 return ans; 13 } 14 bool check

POJ 3318:Matrix Multiplication(随机算法)

http://poj.org/problem?id=3318 题意:问A和B两个矩阵相乘能否等于C. 思路:题目明确说出(n^3)的算法不能过,但是通过各种常数优化还是能过的. 这里的随机算法指的是随机枚举矩阵C的一个位置,然后通过A*B计算是否能够得到矩阵C相应位置的数,如果不等,就直接退出了,如果跑过一定的数量后能够相等,那么就可以判断这个矩阵C等于A*B的.第一次见这样的题目...有点新奇. 暴力算法: 1 #include <cstdio> 2 using namespace std;

微信红包随机算法

最近看了一篇文章,讲微信红包随机算法的.感觉很不错,所以自己实现了下,并进行了简单测试. 算法 算法很简单,不是提前算好,而是抢红包时计算: 红包里的金额怎么算?为什么出现各个红包金额相差很大?答:随机,额度在0.01和剩余平均值*2之间. 实现 实现上述算法的逻辑主要是: public static double getRandomMoney(RedPackage _redPackage) { // remainSize 剩余的红包数量 // remainMoney 剩余的钱 if (_red

加权随机算法

加权随机算法一般应用在以下场景:有一个集合S,里面比如有A,B,C,D这四项.这时我们想随机从中抽取一项,但是抽取的概率不同,比如我们希望抽到A的概率是50%,抽到B和C的概率是20%,D的概率是10%.一般来说,我们可以给各项附一个权重,抽取的概率正比于这个权重.那么上述集合就成了: {A:5,B:2,C:2,D:1} 方法一: 扩展这个集合,使每一项出现的次数与其权重正相关.在上述例子这个集合扩展成:{A,A,A,A,A,B,B,C,C,D}然后就可以用均匀随机算法来从中选取. 好处:选取的

权重随机算法的java实现

一.概述 平时,经常会遇到权重随机算法,从不同权重的N个元素中随机选择一个,并使得总体选择结果是按照权重分布的.如广告投放.负载均衡等. 如有4个元素A.B.C.D,权重分别为1.2.3.4,随机结果中A:B:C:D的比例要为1:2:3:4. 总体思路:累加每个元素的权重A(1)-B(3)-C(6)-D(10),则4个元素的的权重管辖区间分别为[0,1).[1,3).[3,6).[6,10).然后随机出一个[0,10)之间的随机数.落在哪个区间,则该区间之后的元素即为按权重命中的元素. 实现方法

百钱百鸡,用高中数学优化算法

背景介绍 学习算法的道路上总会有各种各样的感受,偶然间碰到一个源自我国的算法问题,百钱百鸡问题,貌似很经典的问题了,可是我才刚刚知道,感觉自己太LOW了.题目是出自古代的一本叫做算经的书,原文是文言文就不往出贴了,贴了也看不懂,说大家能听懂的话就是: 有公鸡,母鸡,小鸡三种鸡,公鸡5块钱一只,母鸡三块钱一只,小鸡一块钱三只,要求用一百块钱买上面三种鸡(都要有),并且三种鸡总数是一百只,要求所有的解法. 分析 在感叹古人物价的同时,思考题目,其实很简单,只需要满足两个条件: 公鸡 + 母鸡 + 小