VOJ - Ran and the Lock Code (规律+二分)

Ran and the Lock Code

题目链接: Ran and the Lock Code Gym - 101778B

题意

给你一个n和a要你构造一个含n个正数的序列,并满足这个序列里所有数的平均数是a,现在要求这个序列里最多能有多少不同的数字。


思路

因为这些数字的平均数是a嘛,所以就非常容易的想到另外的数字在a的左右两侧平均分布,如果是偶数,就在a左右取相等个数的,如果是奇数就夺取一个a。这样的答案就是min(n,2*a-1);

但是,这样的结果肯定是不够的,因为这样取不到2a了,要取到2a只需要在多取一个1和a-1即可。以此类推这样就可以从2a开始向后取过去了。

假设从2a开始以后的有m个数字,那么这些数字所带来的偏差量就是(a+a+m-1) * m/2 ,而现在能抵消最多的是 (a-1)*剩下的数字

不难得到这是一个单调的函数,二分即可。(PS:如果二分有问题,一定要反复检查二分的公式)


代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mp make_pair

typedef double db;
typedef long long ll;
const int INF = (int)0x3f3f3f3f;
const int MAXN = (int)1e5+7;

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int T;
    cin >> T;
    while (T --){
        ll n,a;
        cin >> n >> a;
        ll ans = min(n,2*a-1);
        ll l,r;
        n -= ans;
        if (n > 0){
            l = -1,r = n;   //这里二分我出现了一个问题,本来应该一步到位的算法,我需要加上一个判断条件
            while (l <= r){ //看来我的功力还不够啊
                ll m = (l+r)/2;
                if ((a-1)*(n-m) >= (a+a+m-1)*(m)/2)   l = m+1;  //对就是这个二分公式有问题
                else  r = m-1;
            }
            ans += r;
        }
        cout << ans << endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值