随机化习题集

本文介绍了一种求解绝对众数的算法,通过摩尔投票法和随机化技巧找到一组数经模运算后可能出现的绝对众数。利用数学性质缩小候选模数范围,并通过代码实现验证解的有效性。

一.G - Yet Another mod M (atcoder.jp)

        (1)题目大意

                给定你n个数,让你求一个模数m,使得所有数模上m后,出现了绝对众数(指这个数在原序列中出现的次数>n/2)。

        (2)解题思路

                对于一个区间的绝对众数,我们可以采取摩尔投票法消除,最后出现的一定是绝对众数,或者不存在绝对众数。而对于这个题目我们的目标是模上m后的绝对总数,假定x和y都是绝对众数,那么又(x - y) % m = 0,我们随即化选择k次,那么正确率为1-(3/4)^k,那么m肯定是x-y的因子,然后判断一下是否符合原序列条件即可。

         (3)代码实现

#include "bits/stdc++.h"
using namespace std;
const int N = 5010;
int a[N],n;
void check(int x)
{
    if(x < 3) return ;
    map <int,int> mp;
    for(int i = 1;i <= n;i++) {
        if(++mp[a[i] % x] > n / 2){
            cout << x << endl;
            exit(0);
        }
    }
}
void solve()
{
    int s = 0,t = 0;
    while(s == t) s = rand() % n,t = rand() % n;
    s ++,t ++;
    int val = abs(a[s] - a[t]);
    for(int i = 1;i <= val / i;i++)
        if(val % i == 0)
            check(i),check(val / i);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin >> n;
    for(int i = 1;i <= n;i++) cin >> a[i];
    srand(time(0));
    int T = 50;
    while(T --) solve();
    cout << -1 << endl;
    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值