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

Posted birchtree

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1114E(数学+随机算法)相关的知识,希望对你有一定的参考价值。

题面

传送门

分析

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

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

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

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

可以证明错误的概率< (1.86185 imes10?^{-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
",x);
    fflush(stdout);
    int ans=0;
    scanf("%d",&ans);
    return ans;
} 
int ask2(int x){
    printf("> %d
",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
",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
",x-ans*(n-1),ans);
}


以上是关于Codeforces 1114E(数学+随机算法)的主要内容,如果未能解决你的问题,请参考以下文章

codeforces#1305F. Kuroni and the Punishment(随机算法)

[Codeforces 1295F]Good Contest(DP+组合数学)

解题报告(十八)Codeforces - 数学题目泛做(难度:2000 ~ 3000 + )

备战数学建模21-马尔可夫算法

Codeforces 1106F Lunar New Year and a Recursive Sequence (数学线性代数线性递推数论BSGS扩展欧几里得算法)

随机梯度下降法的数学基础