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;
    }
}


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