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
- poj 2886 Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies?
- poj 2886 Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies?
- poj 2886 Who Gets the Most Candies?
- POJ 2886 - Who Gets the Most Candies?
- POJ 2886 - Who Gets the Most Candies?
- poj 2886 Who Gets the Most Candies?
- poj 2886 Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies?
- POJ 2886: Who Gets the Most Candies?
- poj 2886 Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies?
- poj 2886 Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies?
- poj 2886 Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies?
- POJ:2886 Who Gets the Most Candies?
- CodeForces 281c Rectangle Puzzle 计算几何
- 编程之美--2.1 求二进制数中1的个数
- c++ try_catch throw
- hdoj2767 Proving Equivalences(强连通分量+缩点)
- Eclipse+ADT对android应用签名打包详解
- POJ 2886 Who Gets the Most Candies?
- LeetCode OJ - Reverse Nodes in k-Group
- 【排序】表插入排序算法(C语言版)
- 算法导论习题解-第24章单源最短路径
- HDOJ1018 神奇的log
- C++ RasDial之调用RasEnumEntries遍历系统中存在的宽带连接名称
- HOJ 12811 单词对比(很巧的处理方法,运用26个字母的个数)
- Python学习笔记02 变量和程序的编写
- uva 1541 - To Bet or Not To Bet(记忆化+概率)