• POJ 2886 【线段树模拟约瑟夫环】.cpp


    题意:

      一群小孩顺时针坐然后在玩约瑟夫环的游戏..

      从第k个小孩开始..每个被选中的孩子扔出手中的纸牌..

      然后按着纸牌上面的数找下一个被选中的小孩..

      如果牌中的数是正数就顺时针数..

      如果是负数就逆时针数..

      

      其中第 i 个被选中的小孩会得到f( i )颗糖..

      f( i )表示 i 的正因子个数..

     

      要求是找出得到糖最多的孩子个数..

      

    输入:  

      n k 表示有n个小孩..从第k个开始

      接下来 n 行有n个小孩的名字和他手上的牌的编号..

     

    思路:

      一开始想的是暴力找出这个小孩..

      但是会很麻烦..

      然后这里就用到了反素数了..

      反素数:<http://acm.nenu.edu.cn/us/?p=91>

      找出f[ j ] > f[ i ] : f[ j ]为 j 的正因子个数..

      然后就可以找出n之前正因子最多的那个数 即 得糖最多的那个小孩编号 ans..

      再找出这个小孩是谁..

     

      用线段树模拟找的过程..感觉跟二分有点像~感觉..

     

    Tips:

      ※ 改的是 rt 是 sum 的..但是输入的per的数据是 l 和 r

      ※ 还有一个让我很纠结的就是根据数的正负向左数还是向右数..

     

    Code:

    View Code
     1 #include <stdio.h>
     2 #include <cstring>
     3 
     4 const int MAXN = 500010;
     5 
     6 struct P
     7 {
     8     char name[20];
     9     int sum;
    10 }per[MAXN];
    11 int sum[MAXN<<2];
    12 
    13 int antiprime[]={1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,
    14                  7560,10080,15120,20160,25200,27720,45360,50400,55440,83160,110880,
    15                  166320,221760,277200,332640,498960,554400,665280};
    16 int factorNum[]={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,
    17                  100,108,120,128,144,160,168,180,192,200,216,224};
    18 
    19 void pushup(int rt)
    20 {
    21     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    22 }
    23 
    24 void creat(int l, int r, int rt)
    25 {
    26     if(l == r) {
    27         scanf("%s %d", per[l].name, &per[l].sum);
    28         sum[rt] = 1;
    29         return;
    30     }
    31     int mid = (l+r)>>1;
    32     creat(l, mid, rt<<1);
    33     creat(mid+1, r, rt<<1|1);
    34     pushup(rt);
    35 
    36 }
    37 
    38 int modify(int k, int l, int r, int rt)
    39 {
    40     if(l == r) {
    41         sum[rt]--;
    42         return l;
    43     }
    44     int mid = (l+r)>>1;
    45     int loc;
    46     if(k <= sum[rt<<1]) loc = modify(k, l, mid, rt<<1);
    47     else loc = modify(k-sum[rt<<1], mid+1, r, rt<<1|1);
    48     pushup(rt);
    49     return loc;
    50 }
    51 
    52 int main()
    53 {
    54     int i, j;
    55     int n, k;
    56     int loc, tmp;
    57     int ans;
    58     while(scanf("%d %d", &n, &k) != EOF)
    59     {
    60         creat(1, n, 1);
    61 
    62         for(i = 0; i < 36; ++i) if(antiprime[i] <= n) ans = i;
    63 
    64         k = ((k-1)%n+n)%n+1;
    65         loc = modify(k, 1, n, 1);
    66 
    67         for(i = 1; i < antiprime[ans]; ++i) {
    68             if(per[loc].sum > 0) k = ((k+per[loc].sum - 2)%sum[1] + sum[1])%sum[1] + 1;
    69             else k = ((k+per[loc].sum-1)%sum[1] + sum[1])%sum[1] + 1;
    70             loc = modify(k, 1, n, 1);
    71         }
    72 
    73         printf("%s %d\n", per[loc].name, factorNum[ans]);
    74     }
    75     return 0;
    76 }

    题目链接:http://poj.org/problem?id=2886

  • 相关阅读:
    spring data jpa @index无法创建索引
    vue form绑定数据后只能显示不能编辑
    vue dialog每次打开会展示上一次数据(转载)
    vue-i18n突然所有的都解析不出来了
    sass计算高度
    动态指定日志路径(logback)
    Springboot配置文件内容加密
    java环境变量修改后不生效
    SOAP和REST
    Git配置别名
  • 原文地址:https://www.cnblogs.com/Griselda/p/2725791.html
Copyright © 2020-2023  润新知