hdu 5565 Clarke and baton 二分

Clarke and baton

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://acm.hdu.edu.cn/showproblem.php?pid=5565

Description

Clarke is a patient with multiple personality disorder. One day, Clarke split into n guys, named 1 to n.
They will play a game called Lose Weight. Each of Clarkes has a weight a[i]. They have a baton which is always in the hand of who has the largest weight(if there are more than 2 guys have the same weight, choose the one who has the smaller order). The one who holds the baton needs to lose weight. i.e. a[i] decreased by 1, where i is the guy who holds the baton.
Now, Clarkes know the baton will be passed q times. They want to know each one's weight after finishing this game.

Input

The first line contains an integer T(1≤T≤10), the number of the test cases.
Each test case contains three integers n,q,seed(1≤n,q≤10000000,∑n≤20000000,1≤seed≤109+6), seed denotes the random seed.
a[i] generated by the following code.

long long seed;
int rand(int l, int r) {
static long long mo=1e9+7, g=78125;
return l+((seed*=g)%=mo)%(r-l+1);
}

int sum=rand(q, 10000000);
for(int i=1; i<=n; i++) {
a[i]=rand(0, sum/(n-i+1));
sum-=a[i];
}
a[rand(1, n)]+=sum;

Output

Each test case print a line with a number which is (b[1]+1)xor(b[2]+2)xor...xor(b[n]+n), where b[i] is the ith Clarke's weight after finishing the game.

Sample Input

1
3 2 1

Sample Output

20303

HINT

 

题意

给你1e7个数,每次可以使最大的数减一,可以减Q次

然后问你最后每个数亦或起来的答案是多少

题解:

二分答案,二分最后剩下来的最大的数是多少

然后我们注意一下,有可能Q次并没有减完,那么我们就让前面的去减一就好了

复杂度nlogn

代码

#include<iostream>
#include<stdio.h>
using namespace std;
long long seed;
long long a[10000005];
int n,q;
int rand(int l, int r) {
    static long long mo=1e9+7, g=78125;
    return l+((seed*=g)%=mo)%(r-l+1);
}
int check(int x)
{
    long long k = 0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]<x)continue;
        k+=a[i]-x;
    }
    if(k>q)return 0;
    return 1;
}
int main()
{
    int t;scanf("%d",&t);
    for(int cas=1;cas<=t;cas++)
    {

        scanf("%d%d%I64d",&n,&q,&seed);
        int sum=rand(q, 10000000);
        for(int i=1; i<=n; i++) {
            a[i]=rand(0, sum/(n-i+1));
            sum-=a[i];
        }
        a[rand(1, n)]+=sum;
        //for(int i=1;i<=n;i++)
        //    scanf("%d",&a[i]);
        long long l = -10000000000LL,r = 1000000000000LL;
        while(l<=r)
        {
            long long mid = (l+r)>>1;
            if(check(mid))r=mid-1;
            else l=mid+1;
        }
        long long ans = 0;
        for(int i=1;i<=n;i++)
        {
            if(a[i]<=l)continue;
            q-=(a[i]-l);
        }
        for(int i=1;i<=n;i++)
        {
            if(a[i]<l)
            {
                ans^=(a[i]+i);
            }
            else
            {
                if(q==0)
                {
                    ans^=(l+i);
                }
                else
                {
                    ans^=(l-1+i);
                    q--;
                }
            }
        }
        printf("%I64d\n",ans);
    }
}

 

posted @ 2015-11-14 23:09  qscqesze  阅读(305)  评论(0编辑  收藏  举报