題目連接:http://acm.hdu.edu.cn/showproblem.php?pid=6040
【題意】給定一個生成函數,利用該生成函數生成n個數。給出生成函數的初值A,B,C一個大小爲m的B數組,求解第bi+1小的數是什麼。B數組滿足條件:如果b_i < b_k and b_j < b_k and b_i != b_j,那麼b_i+b_j < b_k。
【分析】比賽期間一直很迷B數組的限制條件,賽後看了題解才恍然大悟。由於B數組限制的存在,當與n取最大1000w時,B數組去重後最多不會超過40個,具體個數查看斐波契那函數,同時B數組去重後的數字和在2n左右,具體數額和證明可以自行推理。如此就可以利用類型快排的方法進行求解,具體爲現對B數據進行排序,從最大的數開始求解,如此求b_i時就可以只使用1-b_(i-1)了,詳細可以參考代碼理解。
【代碼】
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define Uint unsigned int
struct Node{
int v,idx;
Uint ans;
}b[110];
Uint nob[10001000];
Uint A,B,C;
bool cmp(Node n1,Node n2){
return n1.v>n2.v;
}
bool cmp2(Node n1,Node n2){
return n1.idx<n2.idx;
}
unsigned x = A, y = B, z = C;
unsigned rng61() {
unsigned t;
x ^= x << 16;
x ^= x >> 5;
x ^= x << 1;
t = x;
x = y;
y = z;
z = t ^ x ^ y;
return z;
}
int main(){
int n,m,cas=1;
while(~scanf("%d %d %u %u %u",&n,&m,&A,&B,&C)){
for(int i=0;i<m;++i){
scanf("%d",&b[i].v);
b[i].idx=i;
}
sort(b,b+m,cmp);
x=A;y=B;z=C;
for(int i=0;i<n;++i)
nob[i]=rng61();
nth_element(nob,nob+b[0].v,nob+n);
b[0].ans=nob[b[0].v];
for(int i=1;i<m;++i){
if(b[i].v==b[i-1].v){
b[i].ans=b[i-1].ans;
continue;
}
nth_element(nob,nob+b[i].v,nob+b[i-1].v);
b[i].ans=nob[b[i].v];
}
sort(b,b+m,cmp2);
printf("Case #%d:",cas++);
for(int i=0;i<m;++i)
printf(" %u",b[i].ans);
cout<<endl;
}
}