poj 2886 (线段树+反素数打表) Who Gets the Most Candies?

http://poj.org/problem?id=2886

一群孩子从编号1到n按顺时针的方向围成一个圆,每个孩子手中卡片上有一个数字,首先是编号为k的孩子出去,如果他手上的数字m是正数,那么从他左边(顺时针)开始第m个孩子出去,如果是负的

那么从他的右边(也就是逆时针)开始第m个孩子出去~~~一直到所有的孩子出去,另外,第p个出去的孩子可以得到的糖果数量是p的约数个数,问能得到最多糖果的孩子的名字和得到的糖果数目

关于公约数最多的问题,可以利用到反素数,可以首先先打表反素数和对应的约数个数,找出约数最多的次数p,p肯定是不大于n的,然后就是模拟孩子出去的情况,只要模拟p次就行

然后用线段树模拟,与上一题插队差不多,记录下每个区间的人数,每次的顺序k表示第k个有人的区间更新为空

code

 1 #include<cstdio>
 2 using namespace std;
 3 struct point {
 4     int l,r;
 5     int mark;//记录每个区间人数
 6 };
 7 point tree[500001*4];
 8 char jjc[500001][10];
 9 int a[500001],pos;
10 int prime[]={ //反素数
11     1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,
12     20160,25200,27720,45360,50400,55440,83160,110880,166320,221760,277200,332640,498960,
13     554400
14 };
15 int numb[]={ //对应的约数个数
16     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,
17     144,160,168,180,192,200,216
18 };
19 void build (int i,int left,int right)
20 {
21     tree[i].l=left,tree[i].r=right;
22     tree[i].mark=tree[i].r-tree[i].l+1;
23     if (left==right) { return ;}
24     int mid=(left+right)/2;
25     build(i*2,left,mid);
26     build(i*2+1,mid+1,right);
27 }
28 void  update(int i,int ans)
29 {
30     if (tree[i].l==tree[i].r)
31     {
32         pos=tree[i].l;
33         tree[i].mark--;
34         return ;
35     }
36     if (ans<=tree[i*2].mark)
37        update(i*2,ans);
38     else
39        update(i*2+1,ans-tree[i*2].mark);
40     tree[i].mark=tree[i*2].mark+tree[i*2+1].mark;
41 }
42 int main()
43 {
44     int n,k,i,w,m;
45     while (scanf("%d %d",&n,&k)==2)
46     {
47         for (i=1;i<=n;i++)
48             scanf("%s %d",&jjc[i],&a[i]);
49         build(1,1,n);
50         w=0;
51         for(i=0;prime[i]<=n;i++)w=i;
52         pos=0;m=prime[w];
53         a[0]=0;
54         while (m--)
55         {
56             int num=tree[1].mark;
57             if (a[pos]>0)
58                k=((k+a[pos]-2)%num+num)%num+1;
59             else
60                k=((k+a[pos]-1)%num+num)%num+1;
61             update(1,k);
62         }
63         printf("%s %d\n",jjc[pos],numb[w]);
64     }
65     return 0;
66 }
时间: 2024-11-02 17:09:31

poj 2886 (线段树+反素数打表) Who Gets the Most Candies?的相关文章

poj 2886 线段树的更新+反素数

Who Gets the Most Candies? Time Limit: 5000 MS Memory Limit: 0 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description N children are sitting in a circle to play a game. The children are numbered from

POJ 2886 线段树单点更新

转载自:http://blog.csdn.net/sdj222555/article/details/6878651 反素数拓展参照:http://blog.csdn.net/ACdreamers/article/details/25049767 题目大意就是一群熊孩子做游戏,第一个出队的人是编号为k的人.此后出队的人就是按照前一个人手里的编号.如果是正数+m就是这个人的左边的第m个人.如果是负数-m,就是 这个人的右边第m个人.由于这个人出队了.对下一个人有影响,所以+m的时候,是k+m-1.

poj2886--Who Gets the Most Candies?(线段树+反素数)

题目链接点击打开链接 题目大意:给出n个人的姓名和手里的一个号码,n个人排成一圈,号码有正有负,代表着正向还是反向移动k个位置,比赛从第k个人开始,把被选到的人踢出,问按踢出的顺序中因子数最多的是谁? 建立线段树,把n个人被踢的顺序找到,然后求出n个人中因子数最多的(最小的数)是谁,这里要用到反素数,详看链接点击打开链接 #include <cstdio> #include <cstring> #include <algorithm> using namespace s

Who Gets the Most Candies?(线段树 + 反素数 )

Who Gets the Most Candies? Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Description N children are sitting in a circle to play a game. The children are numbered from 1 to N in clockwise order. Each of th

POJ - 2886线段树+线性筛

题意就是给你n个人,每个人有一个名字和A,如果A为正则向左找第A个,否则向右找第-A个,每找到一个就出列,然后第i个人出列的F(i)是i的所有因子个数 输出最大的F(i)和对应的名字 先用线性筛找出第几个出列的值最大maxn,那么求到maxn就可以了. 用线段树记录空位,k表示当前需要从剩余人第几个位置寻找,只要推出k,则转化为线段树的求位置的模型 #include<iostream> #include<cstdio> #include<cstring> using n

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

poj 2777 线段树的区间更新

Count Color Time Limit: 1000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description Chosen Problem Solving and Program design as an optional course, you are required to solve al

转载::POJ 2991 线段树+计算几何(有c++结构体操作)

POJ 2991 线段树+计算几何 (2011-02-27 21:13:44) 转载▼ 标签: 杂谈 分类: OI 话说这一题真的是很恶心很恶心,不过确实改变了我对线段树的一些看法,算是很经典的题目. 题意:有一个吊车由很多个不同长度的线段组成,一开始是一条长直线起点在(0,0),尾节点在(0,sum[n]),每条线段之间的夹角的初始值是180度.然后有一些操作a. b将第a条线段和a+1之间的夹角变成b度,经过每一次操作都要求出尾节点的坐标. 首先要用到一个计算几何的知识(没学过..请教而来)

poj 2750(线段树的动态规划)

Potted Flower Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4186   Accepted: 1581 Description The little cat takes over the management of a new park. There is a large circular statue in the center of the park, surrounded by N pots of f