zoukankan      html  css  js  c++  java
  • 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);
    }
    
    
    
    
  • 相关阅读:
    yii之behaviors
    查看windows系统信息
    idm chrome扩展被阻止解决办法
    音乐乐理基础
    bootstrap4
    七牛上传整合CI
    提升上传速度
    卡漫绘图
    指针的操作
    定语从句八个易混淆
  • 原文地址:https://www.cnblogs.com/birchtree/p/10360859.html
Copyright © 2011-2022 走看看