POJ 2886 Who Gets the Most Candies?

来源:互联网 发布:整容后遗症 知乎 编辑:程序博客网 时间:2024/06/13 02:42

题目链接:点击打开链接


题意:输入N,K,表示N个小朋友围成一个圈,每个小朋友手拿一张卡片上写着一个数,有正有负,开始时顺时针第K个小朋友出队,然后如果他手里的卡片数m是正数下一个出队的就是他左侧第m个,如果是负的就是右侧第m个,第i个出队的小朋友可以获得 i 的约数个糖果,问所有小朋友都出队后获得最多糖果的是谁,输出名字和糖果数。


本题需要一个知识:反素数,对于一个数n,如果所有小于n的数的约数都没有n多,则n是反素数。具体请百度百科。本题只要提前打表出反素数,然后找出小于N且最接近N的反素数,就可以知道获得最多糖果的是第几个出队的小朋友。


求反素数的代码:(dfs搜索,剪枝需要两条性质,请百度百科反素数)

#include <cstdio>#include <iostream>using namespace std;int prime[20]={1,2,3,5,7,11,13,17,19,23,31,34};int bestsum,maxnum;int n;void get(int cur,int k,int num,int limit){    int i,temp;    if(k>10)        return ;    if(num>maxnum){            maxnum=num;            bestsum=cur;    }    if(num==maxnum&&cur<bestsum){            bestsum=cur;    }    temp=cur;    for(int i=1;i<=limit;i++){          if(temp*prime[k]>=n)            break;          temp*=prime[k];          get(temp,k+1,num*(i+1),i);    }}int antiprime[50];int divnum[50];int main(){    n=500010;    for(int i=35;i>=1;i--){            maxnum=0;bestsum=0;            get(1,1,1,20);            antiprime[i]=bestsum;            divnum[i]=maxnum;            n=bestsum;    }    for(int i=1;i<=35;i++){            cout<<antiprime[i]<<" "<<divnum[i]<<endl;    }    return 0;}

然后每次需要查询当前队中第i个小朋友的位置,这就需要线段树来维护每个区间的小朋友数。

注意设每次要查询的小朋友数为next,当前卡片上的数是正和负时求下一个next方法不一样,如果是正的因为之前位置的人出队了,所以实际查询的人数应该-1,是负的则不受影响。

本题完整代码:

#include <iostream>#include <cstdio>#include <cstring>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define MAX 500010using namespace std;int antiprime[40]={1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,20160,25200,27720,45360,50400,55440,83160,110880,166320,221760,277200,332640,498960,554400};int divnum[40]={1,2,3,4,6,8,9,10,12,16,18,20,24,30,32,36,40,48,60,64,72,80,84,90,96,100,108,120,128,144,160,168,180,192,200,216};int sum[MAX<<2];int N,K;char name[MAX][20];int card[MAX];void pushup(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build (int l,int r,int rt){    if(l==r){sum[rt]=1;return ;}    int m=(l+r)>>1;    build(lson);    build(rson);    pushup(rt);}int query(int k,int l,int r,int rt){    if(l==r){        sum[rt]--;        return l;    }    int m=(l+r)>>1;    int res;    if(sum[rt<<1]>=k) res=query(k,lson);    else {        k-=sum[rt<<1];        res=query(k,rson);    }    pushup(rt);    return res;}void init(){    for(int i=1;i<=N;i++){            scanf("%s%d",name[i],&card[i]);    }    build(1,N,1);}int main(){    while(~scanf("%d%d",&N,&K)){            init();            int nowP=K;            int next=K;            int pripos=1;            while(antiprime[pripos]<=N) pripos++;            pripos--;            for(int i=1;i<=antiprime[pripos];i++){                nowP=query(next,1,N,1);                if(sum[1]==0)break;                if(card[nowP]>0){                    next=(card[nowP]%sum[1]+next-1)%sum[1];                }                else{                    next=(card[nowP]%sum[1]+next)%sum[1];                }                if(next<=0)next+=sum[1];            }            printf("%s %d\n",name[nowP],divnum[pripos]);    }    return 0;}


0 0
原创粉丝点击