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出了nn个自己,序号从11nn。
他们准备玩一个减肥游戏,每一个克拉克都有一个体重a[i]a[i]。他们有一个接力棒,这个接力棒任何时刻总是在最重的克拉克(如果重量相同则在序号最小的)的手中,得到这个接力棒的克拉克需要减肥,使得体重变成a[i]-1a[i]1,随后接力棒便传递到下一个人(可以是自己)的手中。
现在克拉克们知道接力棒一共被传递过qq次,他们想知道最终每一个克拉克的体重分别是多少。
输入描述
第一行一个整数T(1 \le T \le 10)T(1T10),表示数据的组数。
每组数据只有一行三个整数n, q, seed(1 \le n, q \le 10000000, \sum n \le 20000000, 1 \le seed \le 10^9+6)n,q,seed(1n,q10000000,n20000000,1seed109+6),分别表示克拉克的个数、接力棒传递次数还有一个随机种子。
a[i]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;
输出描述
每组数据输出一行一个数,这个数ansans是这样得到的。
假设b[i]b[i]是最终克拉克们的体重,则ans=(b[1]+1) xor (b[2]+2) xor ... xor (b[n]+n)ans=(b[1]+1)xor(b[2]+2)xor...xor(b[n]+n),其中xorxor是异或操作。
输入样例
1
3 2 1
输出样例
20303
Hint
首先a[1]=20701, a[2]=31075, a[3]=26351a[1]=20701,a[2]=31075,a[3]=26351
第一次接力棒在22号克拉克手上,所以a[2]=31074a[2]=31074。
第二次接力棒在22号克拉克手上,所以a[2]=31073a[2]=31073。
所以答案等于(20701+1)xor(31073+2)xor(26351+3)=20303(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;
}





posted on 2015-11-20 16:34  光速小子  阅读(164)  评论(0编辑  收藏  举报

导航