POJ:2886 Who Gets the Most Candies?
2014-03-13 19:08
387 查看
线段树模拟约瑟夫环+反素数。
网上说这个地方是模拟约瑟夫环,其实我感觉没有约瑟夫环那样麻烦。实际上只需要求出去掉某个人之后,卡牌上对应的人从左往右数是第几个即可。这样假设第k个人出列,它对应的编号是A。如果A大于0说明对应的人在k的右边,否则左边。原来人数是n,k出列以后就是n-1了。那么这个A对应的是从左往右第(k-1+A-1)%(n-1)+1。前面的
k-1表示编号从0开始这是为了方便取余,括号里后面有个-1意思是去掉k这个人,所以要减一,因为A在右边,最后的+1是为了恢复编号从1开始。如果A小于0则((k-1+A)%(n-1)+(n-1))%(n-1)+1因为此时A在左边,其实相当于减了一个数因为A是负的,k在它右边所以不用考虑-1,注意为了避免结果为负,要加上一个模。
网上说这个地方是模拟约瑟夫环,其实我感觉没有约瑟夫环那样麻烦。实际上只需要求出去掉某个人之后,卡牌上对应的人从左往右数是第几个即可。这样假设第k个人出列,它对应的编号是A。如果A大于0说明对应的人在k的右边,否则左边。原来人数是n,k出列以后就是n-1了。那么这个A对应的是从左往右第(k-1+A-1)%(n-1)+1。前面的
k-1表示编号从0开始这是为了方便取余,括号里后面有个-1意思是去掉k这个人,所以要减一,因为A在右边,最后的+1是为了恢复编号从1开始。如果A小于0则((k-1+A)%(n-1)+(n-1))%(n-1)+1因为此时A在左边,其实相当于减了一个数因为A是负的,k在它右边所以不用考虑-1,注意为了避免结果为负,要加上一个模。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <vector> #include <queue> #include <set> #include <map> #include <algorithm> #define ll long long #define INF 2139062143 #define inf -2139062144 #define MOD 20071027 #define MAXN 500005 #define LEN 555555<<2 using namespace std; char name[MAXN][15]; int val[MAXN]; struct Segment_tree { private: int sum[LEN],sz; void pushup(int o) { sum[o]=sum[o<<1]+sum[o<<1|1]; } int myquery(int o,int L,int R,int v) { sum[o]--; if(L==R) return L; int M=(L+R)/2; if(v<=sum[o*2]) return myquery(o*2,L,M,v); else return myquery(o*2+1,M+1,R,v-sum[o*2]); } public: void clear(int n) { sz=n; int len=n<<2; for(int i=0; i<=len; ++i) sum[i]=0; } void build(int o,int L,int R) { if(L==R) { scanf("%s%d",&name[L],&val[L]); sum[o]=1; } else { int M=(L+R)>>1; build(o<<1,L,M); build(o<<1|1,M+1,R); pushup(o); } } int query(int p) { return myquery(1,1,sz,p); } }; Segment_tree tree; int RPrime[]= { //反素数 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 fact[]= { //反素数约数个数 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 main() { int n,k; //freopen("outmy.txt","w",stdout); while(scanf("%d%d",&n,&k)!=EOF) { tree.clear(n); int v=0; for(int i=0; RPrime[i]<=n ; ++i)v=i; tree.build(1,1,n); int p=k,u=0; for(int i=1,j=n-1; i<=RPrime[v]; ++i,--j) { u=tree.query(p); if(j==0) break; if(val[u]>0) p=((p-2+val[u])%j+j)%j+1; else p=((p-1+val[u])%j+j)%j+1; } printf("%s %d\n",name[u],fact[v]); } return 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? 线段树动态求第k大的数
- 【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? (线段树)
- poj2886--Who Gets the Most Candies?(线段树+反素数)
- 挑战练习题3.3 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?
- POJ2886-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?(反素数+线段树)