• 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
  • 相关阅读:
    第二次刷题感受——路漫漫其修远兮,吾将上下而求索。
    刷题就是照镜子——第一次刷2008年初赛题感受
    第一次集训刷题感受
    我的第一个博客
    预测房价的回归问题
    电影评论的情感极性分析
    语音助手是这样子的(二)
    语音助手是这样子的(一)
    软工第一次作业
    2020软件工程第五次作业_第二组
  • 原文地址:https://www.cnblogs.com/luyingfeng/p/3564173.html
Copyright © 2020-2023  润新知