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); } }