Clarke and baton
克拉克是一名人格分裂患者。某一天,克拉克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
首先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
打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;
}