poj2886--Who Gets the Most Candies?(线段树+反素数)

题目链接点击打开链接

题目大意:给出n个人的姓名和手里的一个号码,n个人排成一圈,号码有正有负,代表着正向还是反向移动k个位置,比赛从第k个人开始,把被选到的人踢出,问按踢出的顺序中因子数最多的是谁?

建立线段树,把n个人被踢的顺序找到,然后求出n个人中因子数最多的(最小的数)是谁,这里要用到反素数,详看链接点击打开链接

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define root 1,n,1
#define int_rt int l,int r,int rt
int a[8] = {2,3,5,7,11,13,17,19} ;
int cl[2010000] ;
char str[510000][12] ;
int p[510000] , w[510000] , cnt ;
int n , ans , best ;
void push_up(int rt) {
    cl[rt] = cl[rt<<1] + cl[rt<<1|1] ;
}
void creat(int_rt) {
    if( l == r ) cl[rt] = 1 ;
    else {
        creat(lson) ;
        creat(rson) ;
        push_up(rt) ;
    }
}
int update(int k,int_rt) {
    if( l == r ) {
        cl[rt] = 0 ;
        return l ;
    }
    if( cl[rt<<1] >= k )
        k = update(k,lson) ;
    else
        k = update(k-cl[rt<<1],rson) ;
    push_up(rt) ;
    return k ;
}
void dfs(int dept,int temp,int num) {
    if( dept >= 8 ) return ;
    if( num > best ) {
        best = num ;
        ans = temp ;
    }
    if( num == best && temp < ans ) ans = temp ;
    for(int i = 1 ; i < 25 ; i++) {
        if( n/a[dept] < temp ) break ;
        temp *= a[dept] ;
        dfs(dept+1,temp,num*(i+1)) ;
    }
}
int main() {
    int m , k , i ;
    while( scanf("%d %d", &n, &k) != EOF ) {
        for(i = 1 ; i <= n ; i++) {
            scanf("%s %d", str[i], &p[i]) ;
        }
        creat(root) ;
        cnt = 1 ;
        while( 1 ) {
            m = update(k,root) ;
            w[m] = cnt++ ;
            if( !cl[1] ) break ;
            if( p[m] >= 0 ) {
                k = (k+p[m]-1)%cl[1] ;
                if( !k ) k = cl[1] ;
            }
            else {
                k = (k-cl[1]-1+p[m])%cl[1] ;
                if( !k ) k = 1 ;
                else k = cl[1]+1+k ;
            }
        }
        best = 0 ;
        ans = n ;
        dfs(0,1,1) ;
        for(i = 1 ; i <= n ; i++){
            if( w[i] == ans ) {
                printf("%s %d\n", str[i], best) ;
                break ;
            }
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-11 11:30:19

poj2886--Who Gets the Most Candies?(线段树+反素数)的相关文章

poj 2886 (线段树+反素数打表) Who Gets the Most Candies?

http://poj.org/problem?id=2886 一群孩子从编号1到n按顺时针的方向围成一个圆,每个孩子手中卡片上有一个数字,首先是编号为k的孩子出去,如果他手上的数字m是正数,那么从他左边(顺时针)开始第m个孩子出去,如果是负的 那么从他的右边(也就是逆时针)开始第m个孩子出去~~~一直到所有的孩子出去,另外,第p个出去的孩子可以得到的糖果数量是p的约数个数,问能得到最多糖果的孩子的名字和得到的糖果数目 关于公约数最多的问题,可以利用到反素数,可以首先先打表反素数和对应的约数个数,

Who Gets the Most Candies?(线段树 + 反素数 )

Who Gets the Most Candies? Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status 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 th

poj 2886 Who Gets the Most Candies?(线段树+约瑟夫环+反素数)

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 9934   Accepted: 3050 Case Time Limit: 2000MS Description N children are sitting in a circle to play a game. The children are numbered from 1 to N in clockwise o

Poj2886Who Gets the Most Candies?线段树

约瑟夫环用线段数搞,一脸搞不出来的样子.反素数,太神了,先打表,然后就可以 O(1)找到因子数最多的.ps:哎.这题也是看着题解撸的. #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cs

POJ 2886 Who Gets the Most Candies?(线段树&#183;约瑟夫环)

题意  n个人顺时针围成一圈玩约瑟夫游戏  每个人手上有一个数val[i]   开始第k个人出队  若val[k] < 0 下一个出队的为在剩余的人中向右数 -val[k]个人   val[k] > 0 时向左数val[k]个  第m出队的人可以得到m的约数个数个糖果  问得到最多糖果的人是谁 约瑟夫环问题  n比较大 直接模拟会超时   通过线段树可以让每次出队在O(logN)时间内完成  类似上一道插队的题  线段树维护对应区间还有多少个人没出队  那么当我们知道出队的人在剩余人中排第几个

[poj 2886] 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 oth

poj 2886 Who Gets the Most Candies? 线段树动态求第k大的数

题意: n个小孩站一圈,每个小孩拿一个数字,从第k个孩子开始出局,然后下一个出局的孩子是刚刚出局的孩子之前或之后第v个(刚刚出局的孩子的数字是+v则之后v个,-v则之前v个),这样所有孩子终将出局,第p个出局的孩子得f(p)分,f(p)定义为p的因子个数.求分数最高的孩子. 分析: 设顺时针为正方向,关键是模拟出每次出局的孩子是剩下的孩子中的正方向的第几个,设当前要出局的是第k个,然后要求出第k个小孩的下标(pos)以便下一次计算下一个出局的孩子是第几个,这些步骤可用线段树维护. 代码: //p

POJ2886Who Gets the Most Candies?(线段树之约瑟夫)

约瑟夫问题的升级版,每次出去的是前一个出去的人位置+手上的数字(正往前,负往后).第i个出去的人拿的糖是i的约数的个数.求拿糖最多的人和他的糖果数. 这里用到了反素数的知识,在这直接打表 题目 AC代码: #include<stdio.h> #include<string.h> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int N = 500002; int v[N],sum[N<&

POJ2886 Who Gets the Most Candies? 【线段树】+【单点更新】+【模拟】+【反素数】

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 9416   Accepted: 2868 Case Time Limit: 2000MS Description N children are sitting in a circle to play a game. The children are numbered from 1 to N in clockwise o