HDU 5565:Clarke and baton
Clarke and baton
Accepts: 14
Submissions: 79
Time Limit: 12000/6000 MS (Java/Others)
Memory Limit: 524288/524288 K (Java/Others)
问题描述
克拉克是一名人格分裂患者。某一天,克拉克fork出了n个自己,序号从1到n。 他们准备玩一个减肥游戏,每一个克拉克都有一个体重a[i]。他们有一个接力棒,这个接力棒任何时刻总是在最重的克拉克(如果重量相同则在序号最小的)的手中,得到这个接力棒的克拉克需要减肥,使得体重变成a[i]−1,随后接力棒便传递到下一个人(可以是自己)的手中。 现在克拉克们知道接力棒一共被传递过q次,他们想知道最终每一个克拉克的体重分别是多少。
输入描述
第一行一个整数T(1≤T≤10),表示数据的组数。 每组数据只有一行三个整数n,q,seed(1≤n,q≤10000000,∑n≤20000000,1≤seed≤109+6),分别表示克拉克的个数、接力棒传递次数还有一个随机种子。 a[i]按照以下规则生成: 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;
输出描述
每组数据输出一行一个数,这个数ans是这样得到的。 假设b[i]是最终克拉克们的体重,则ans=(b[1]+1)xor(b[2]+2)xor...xor(b[n]+n),其中xor是异或操作。
输入样例
1 3 2 1
输出样例
20303
Hint
首先a[1]=20701,a[2]=31075,a[3]=26351 第一次接力棒在2号克拉克手上,所以a[2]=31074。 第二次接力棒在2号克拉克手上,所以a[2]=31073。 所以答案等于(20701+1)xor(31073+2)xor(26351+3)=20303
模拟题。
从最大的那个数开始减少,每一轮对当前已经有的数进行减一,减去的次数跟Q进行比较,注意大于Q的时候要 求一个rest。
代码:
#pragma warning(disable:4996) #include <iostream> #include <algorithm> #include <cmath> #include <vector> #include <string> #include <cstring> #include <queue> using namespace std; typedef long long ll; const int maxn = 1e7 + 1; const int mod = 1e9 + 7; const int G = 78125; ll n, q, seed; int a[10000002]; int nu[10000002]; int rand(int lll, int r) { static ll mo = 1e9 + 7, g = 78125; return lll + ((seed *= g) %= mo) % (r - lll + 1); } int main() { //freopen("i.txt","r",stdin); //freopen("o.txt","w",stdout); int t, sum, mt, rest, res, num, cnt; ll ans; scanf("%d", &t); while (t--) { scanf("%lld%lld%lld", &n, &q, &seed); mt = 0; sum = rand(q, 10000000); for (int i = 1; i <= n; i++) { a[i] = rand(0, sum / (n - i + 1)); sum -= a[i]; mt = max(mt, a[i]); } int tmp = rand(1, n); a[tmp] += sum; mt = max(mt, a[tmp]); memset(nu, 0, sizeof(nu)); for (int i = 1;i<=n; i++) { nu[a[i]]++; } num = 0; cnt = 0; for (int i = mt;; i--) { if (cnt >= q) { rest = q - (cnt - num); res = i + 1; break; } if (i >= 0) { num += nu[i]; } cnt += num; } ans = 0; for (int i = 1; i <= n; i++) { if (a[i] < res) { ans ^= (a[i] + i); } else { if (rest > 0) { rest--; ans ^= (res - 1 + i); } else { ans ^= (res + i); } } } printf("%lld\n", ans); } //system("pause"); return 0; }