HDU5785 Hints of sd0061

題目連接: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;
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章