读书人

poj 2886 Who Gets the Most Candies

发布时间: 2012-11-08 08:48:11 作者: rapoo

poj 2886 Who Gets the Most Candies?

题解:

约瑟夫还+反素数

约瑟夫还:线段树处理

发素数:dfs

这个题dfs时,不加上限会超过int

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int maxn=500100;int prime[13]={1,2,3,5,7,11,13,17,19,23};struct TREE{    int l,r;    int sum;}tree[maxn*4];char s[maxn*2][20];int a[maxn*2];int n,m,bestx,bestnum;void dfs(int x,int k,int num,int limit){    if(x>n)return;    if(num>bestnum)    {        bestx=x;        bestnum=num;    }    else if(num==bestnum && x<bestx)    {        bestx=x;    }    int temp=1;    for(int i=1;i<=limit;i++)    {        temp*=prime[k];        if(x*temp>maxn)break;//不加这句话会搜爆,导致RE        dfs(x*temp,k+1,num*(i+1),i);    }}void build(int l,int r,int th){    tree[th].l=l;tree[th].r=r;tree[th].sum=0;    if(l==r)    {        tree[th].sum=1;        return;    }    int mid=(l+r)>>1;    build(l,mid,2*th);    build(mid+1,r,2*th+1);    tree[th].sum=tree[2*th].sum+tree[2*th+1].sum;}void add(int l,int r,int c,int th){    if(l==tree[th].l && r==tree[th].r)    {        tree[th].sum+=c;        return;    }    int mid=(tree[th].l+tree[th].r)>>1;    if(r<=mid)        add(l,r,c,2*th);    else if(l>mid)        add(l,r,c,2*th+1);    tree[th].sum=tree[2*th].sum+tree[2*th+1].sum;}int getnum(int l,int r,int th){    if(l>r)return 0;    if(tree[th].l==l && tree[th].r==r)        return tree[th].sum;    int mid=(tree[th].l+tree[th].r)>>1;    if(r<=mid)        return getnum(l,r,2*th);    else if(l>mid)        return getnum(l,r,2*th+1);    else        return getnum(l,mid,2*th)+getnum(mid+1,r,2*th+1);}int getlabel(int c,int th){    if(tree[th].l==tree[th].r)    {        return tree[th].l;    }    if(tree[2*th].sum>=c)        return getlabel(c,2*th);    else        return getlabel(c-tree[2*th].sum,2*th+1);}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        for(int i=1;i<=n;i++)        scanf("%s%d",s[i],&a[i]);        bestx=1;bestnum=1;        dfs(1,1,1,20);        //xianduan        build(1,n,1);        int num=1,luck=m;        while(num<bestx)        {            //next            add(luck,luck,-1,1);            if(a[luck]>0)            {                a[luck]=a[luck]%(n-num);                if(a[luck]==0)a[luck]=n-num;                if(luck<n && getnum(luck+1,n,1)>=a[luck])                    luck=getlabel(getnum(1,luck,1)+a[luck],1);                else                    luck=getlabel(a[luck]-getnum(luck+1,n,1),1);            }            else            {                a[luck]=a[luck]%(n-num);                if(a[luck]==0)a[luck]=-(n-num);                if(luck>1 && getnum(1,luck-1,1)>=(-a[luck]))                    luck=getlabel(getnum(1,luck,1)+1+a[luck],1);                else                    luck=getlabel(getnum(1,n,1)-((-a[luck])-getnum(1,luck-1,1))+1,1);            }            num++;        }        printf("%s %d\n",s[luck],bestnum);    }    return 0;}


读书人网 >操作系统

热点推荐