克拉克是一名人格分裂患者。某一天,克拉克fork出了nn个自己,序号从11到nn。 他们准备玩一个减肥游戏,每一个克拉克都有一个体重a[i]a[i]。他们有一个接力棒,这个接力棒任何时刻总是在最重的克拉克(如果重量相同则在序号最小的)的手中,得到这个接力棒的克拉克需要减肥,使得体重变成a[i]-1a[i]−1,随后接力棒便传递到下一个人(可以是自己)的手中。 现在克拉克们知道接力棒一共被传递过qq次,他们想知道最终每一个克拉克的体重分别是多少。
第一行一个整数T(1 \le T \le 10)T(1≤T≤10),表示数据的组数。 每组数据只有一行三个整数n, q, seed(1 \le n, q \le 10000000, \sum n \le 20000000, 1 \le seed \le 10^9+6)n,q,seed(1≤n,q≤10000000,∑n≤20000000,1≤seed≤109+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
首先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
打BC时没注意到哎!!
终于又打到div1了
看完题后要好好分析数据的大小再做
我没有仔细看数据大小,以为q的大小为10^9,就搞了个很麻烦的方法
直接用堆模拟O(nlogn) TLE
#include
#include
#include
#include
using namespace std;
const int N = 10000001;
int a[N];
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);
}
struct node
{
int x;
int cnt;
node(){}
node(int xx, int cc)
{
x = xx; cnt = cc;
}
friend bool operator<(const node a, const node b)
{
if(a.x == b.x)
return a.cnt > b.cnt;
return a.x < b.x;
}
};
priority_queue
que; int main(void) { long long n, q; int T; scanf("%d", &T); int i, j; while(T--) { scanf("%I64d%I64d%I64d", &n, &q, &seed); int sum=rand(q, 10000000); for(i=1; i<=n; i++) { a[i]=rand(0, sum/(n-i+1)); sum-=a[i]; } a[rand(1, n)]+=sum; for(i = 1; i <= n; i++) que.push( node(a[i], i) ); while(q--) { node tmp = que.top(); que.pop(); tmp.x--; que.push( tmp ); // printf("%d %d\n", tmp.x, tmp.cnt); } int ans = 0; while(!que.empty()) { node tmp = que.top(); que.pop(); ans ^= tmp.x+tmp.cnt; } printf("%d\n", ans); } return 0; }
#include
#include
#include
using namespace std;
const int N = 10000001;
int a[N];
int s[N];
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 main(void)
{
long long n, q;
int T;
scanf("%d", &T);
int i, j;
while(T--)
{
memset(s, 0, sizeof(s));
scanf("%I64d%I64d%I64d", &n, &q, &seed);
int sum=rand(q, 10000000);
for(i=1; i<=n; i++)
{
a[i]=rand(0, sum/(n-i+1));
sum-=a[i];
}
int tmp = rand(1, n);
a[tmp]+=sum;
for(i = 1; i <= n; i++) s[ a[i] ]++;
for(i = 10000000; q ; i--)
{
while(s[i] && q)
{
s[i]--; s[i-1]++; q--;
}
if(!q) break;
}
tmp = i;
int ans = 0;
int con = 0;
// printf("tmp=%d\n", tmp);
for(i = n; i > 0; i--)
{
if(a[i] < tmp) {ans ^= a[i]+i;continue;}
else if(a[i] >= tmp && con < s[tmp]) {ans ^= tmp+i;con++;}
else ans ^= tmp-1+i;
// printf("ans=%d\n", ans);
}
printf("%d\n", ans);
}
return 0;
}