zoukankan      html  css  js  c++  java
  • POJ 2886 Who Gets the Most Candies?(反素数+线段树)

    点我看题目

    题意 :n个小盆友从1到n编号按顺时针编号,然后从第k个开始出圈,他出去之后如果他手里的牌是x,如果x是正数,那下一个出圈的左手第x个,如果x是负数,那出圈的是右手第-x个,游戏中第p个离开的孩子得到的糖果是f(p)个,f(p)是p的约数的个数。

    思路 : 因为f(p)是p的约数的个数,所以,要用到反素数,反素数的定义及求法反素数s的约数个数比小于它的数的约数个数都多,最大反素数就是要找到的那个得到糖果最多的人。线段树记录的是还剩多少 人未出列。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    
    using namespace std;
    
    const int maxn = 506000 ;
    char ch[maxn][15] ;
    int data[maxn] ;
    
    struct mode
    {
        int l,r ;
        int value,sum ;
    }tree[maxn * 4] ;
    //反素数表
    int rev[37] = {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 revs[37] = {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,1314521};
    
    void build(int v,int l,int r)
    {
        tree[v].l = l ;
        tree[v].r = r ;
        tree[v].value = r-l+1 ;
        if(l == r) return ;
        int mid = (l + r) >> 1 ;
        build(v*2,l,mid) ;
        build(v*2+1,mid+1,r) ;
    }
    
    int query(int v,int x)
    {
        tree[v].value-- ;
        if(tree[v].l == tree[v].r) return tree[v].l ;
        if(x <= tree[v*2].value)
        return query(v*2,x) ;
        else return query(v*2+1,x-tree[v << 1].value) ;
    }
    int main()
    {
        int n, k;
        while(scanf("%d %d",&n,&k) != EOF)
        {
            int i = 0,maxx = 0,p = 0 ;
            while(rev[i] <= n)
            i++ ;
            p = rev[i-1] ;
            maxx = revs[i-1] ;
            build(1,1,n ) ;
            for(int j = 1 ; j <= n ; j++)
            scanf("%s %d",ch[j],&data[j]) ;
            int yy ;
            for(int i = 0 ; i < p ; i++)
            {
                n -- ;
                yy = query(1,k) ;
                if(n == 0) break ;
                if(data[yy] > 0)
                k = (k-1+data[yy]-1) % n + 1 ;
                else k =( (k-1+data[yy])%n+n) % n+1 ;
            }
            printf("%s %d
    ",ch[yy],maxx) ;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    V-Ray Material Library材质名称翻译
    3dMax常用快捷键
    3dMax笔记(韵湖)
    background-size拉伸背景图片
    CSS实现子元素水平垂直居中的6种方式
    JS简易实现“最小栈”
    JS种Array原型方法reverse的模拟实现
    JS数组去重的3种方式
    encodeURIComponent和encodeURI有什么区别
    CSS中的度量单位(px/em/rem/vm/vh/...)
  • 原文地址:https://www.cnblogs.com/luyingfeng/p/3564173.html
Copyright © 2011-2022 走看看