zoukankan      html  css  js  c++  java
  • 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
    ",jjc[pos],numb[w]);
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    函数—函数进阶(二)
    函数—函数进阶(一)
    函数(三)
    函数(二)
    函数(一)
    人丑就要多读书、三元运算、文件处理
    第二章练习题
    Python bytes类型介绍、Python3与2字符串的区别、Python3与2编码总结
    进制运算、字符编码、Python3的执行流程
    去除inline-block元素间间距,比较靠谱的两种办法
  • 原文地址:https://www.cnblogs.com/JJCHEHEDA/p/4761089.html
Copyright © 2011-2022 走看看