• POJ 2886 Who Gets the Most Candies?(线段树·约瑟夫环)


    题意  n个人顺时针围成一圈玩约瑟夫游戏  每一个人手上有一个数val[i]   開始第k个人出队  若val[k] < 0 下一个出队的为在剩余的人中向右数 -val[k]个人   val[k] > 0 时向左数val[k]个  第m出队的人能够得到m的约数个数个糖果  问得到最多糖果的人是谁

    约瑟夫环问题  n比較大 直接模拟会超时   通过线段树能够让每次出队在O(logN)时间内完毕  类似上一道插队的题  线段树维护相应区间还有多少个人没出队  那么当我们知道出队的人在剩余人中排第几个也就能够通过线段树知道他在原始环中排第几个了  

    至于第几个出队的人糖果最多就是求1...n中约数最多的数   能够利用反素数相关知识  

    对于不论什么正整数x 其约数的个数记做g(x) 比如g(1)=1 g(6)=4 假设某个正整数x满足   对于随意i(0<i<x) 都有g(i)<g(x)  则称x为反素数 

    我直接用的别人的反素数表

    #include <cstdio>
    #define lc p<<1, s, mid
    #define rc p<<1|1, mid + 1, e
    #define mid ((s+e)>>1)
    using namespace std;
    const int N = 5e5 + 5;
    int tot[N * 4], val[N];
    //tot维护相应区间还有多少人没出去
    char name[N][20];
    
    int ip[] = {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, 500001
               }; //反素数
    
    int div[] = {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
                };//反素数相应的约数个数
    
    void pushup(int p)
    {
        tot[p] = tot[p << 1] + tot[p << 1 | 1];
    }
    
    void build(int p, int s, int e)
    {
        if(s == e)
        {
            tot[p] = 1;
            return;
        }
        build(lc);
        build(rc);
        pushup(p);
    }
    
    int update(int p, int s, int e, int x)
    {
        int ret;
        if(s == e)
        {
            tot[p] = 0;
            return s;
        }
        if(x <= tot[p << 1]) ret = update(lc, x);
        else ret = update(rc, x - tot[p << 1]);
        pushup(p);
        return ret;
    }
    
    int main()
    {
        int n, k, m, r, ans, pos;
        while(scanf("%d%d", &n, &k) != EOF)
        {
            build(1, 1, n);
            for(int i = 1; i <= n; ++i)
                scanf("%s%d", name[i], &val[i]);
    
            for(int i = 0; ip[i] <= n; ++i)
            {
                m = ip[i];   //m为小于等于n的第一个反素数
                ans = div[i];  //ans相应m的约数个数
            }
    
            r = n; //还剩r个人
            for(int i = 0; i < m; ++i)
            {
                r--;
                pos = update(1, 1, n, k);
                //pos为剩余序列中排第k的人在原始队列中的位置
                if(!r) break;
                if(val[pos] >= 0)   //顺时针
                    k = (k - 1 - 1 + val[pos]) % r + 1;
                //第一个-1是把1開始转换为0開始
                //第二个是删除第k个后如今位于第k-1个 要前进val[pos]步
                //后面的+1是把0開始换回1開始
                else                //逆时针
                    k = ((k - 1 + val[pos]) % r + r) % r + 1;
                //逆时针删除第k个后如今还位于第k个 要后退-val[pos]步
            }
            printf("%s %d
    ", name[pos], ans);
        }
    
        return 0;
    }
    //Last modified :   2015-07-13 19:13
    

    Who Gets the Most Candies?


    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 them has a card with a non-zero integer on it in his/her hand. The game starts from the K-th child, who tells all the others the integer on his card and jumps out of the circle. The integer on his card tells the next child to jump out. Let A denote the integer. If A is positive, the next child will be the A-th child to the left. If A is negative, the next child will be the (A)-th child to the right.

    The game lasts until all children have jumped out of the circle. During the game, the p-th child jumping out will get F(p) candies where F(p) is the number of positive integers that perfectly divide p. Who gets the most candies?

    Input

    There are several test cases in the input. Each test case starts with two integers N (0 < N ≤ 500,000) and K (1 ≤ K ≤ N) on the first line. The next Nlines contains the names of the children (consisting of at most 10 letters) and the integers (non-zero with magnitudes within 108) on their cards in increasing order of the children’s numbers, a name and an integer separated by a single space in a line with no leading or trailing spaces.

    Output

    Output one line for each test case containing the name of the luckiest child and the number of candies he/she gets. If ties occur, always choose the child who jumps out of the circle first.

    Sample Input

    4 2
    Tom 2
    Jack 4
    Mary -1
    Sam 1

    Sample Output

    Sam 3

  • 相关阅读:
    js 计时器小练-20160601
    数位dp入门学习之路(正常枚举“过渡到”dfs枚举)
    An easy problem
    牌型种类 蓝桥杯
    带分数(穷举法) 蓝桥杯赛题
    表达式的转换----->中缀表达式转后缀表达式
    map 的使用
    netsatat 的使用
    两个矩形不相交
    前缀和
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7079464.html
Copyright © 2020-2023  润新知