POJ2886 - Who Gets the Most Candies?

首先需要简化问题,变成循环到第k次时,k是 [1 , n] 内约数个数最多的数字,所以输出第k次是谁jump out 这个队列就可以了。

对于约数个数最多这个问题,要用到反素数,打表直接粘贴的别人的。


/****************************************************/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <stack>
#include <map>
#include <queue>
#include <algorithm>
#include <ctime>
#define EPS 1E-8
#define MAXN 500010
#define INF (~0U >> 2)
#define MOD 1000000007
#define Lson l, mid, rt << 1
#define Rson mid + 1, r, rt << 1 | 1
using namespace std;
typedef long long LL;
/****************************************************/
const int antiprime[]=
{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,554400,665280};

const 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,100,108,120,128,144,160,168,180,
192,200,216,224};

int num[MAXN << 2], n, k;

struct P
{
	char name[12];
	int val;
}ch[MAXN];

void push_up(int rt)
{
	num[rt] = num[rt << 1] + num[rt << 1 | 1];
}
void build(int l, int r, int rt)
{
	if (l == r)
	{
		num[rt] = 1;
		return;
	}
	int mid = (l + r) >> 1;
	build(Lson);
	build(Rson);
	push_up(rt);
}

int update(int x, int l, int r, int rt)
{
	if (l == r)
	{
		num[rt] = 0;
		return l;
	}
	int mid = (l + r) >> 1, ret;
	if (num[rt << 1] >= x)
	{
		ret = update(x, Lson);
	}
	else
	{
		ret = update(x - num[rt << 1], Rson);
	}
	push_up(rt);
	return ret;
}

int main()
{
	while (scanf("%d%d", &n, &k) != EOF)
	{
		build(1, n, 1);
		for (int i = 1; i <= n; i++)
		{
			scanf("%s%d", ch[i].name, &ch[i].val);
		}
		int ix;
		for (int i = 0; i <= 35; i++)
		{
			if(antiprime[i] > n)
			{
				ix = i - 1;
				break;
			}
		}
		int pos = 0;
		int &mod = num[1];
		ch[pos].val = 0;
		for (int i = 0; i < antiprime[ix]; i++) //if (mod != 0)
		{
			if (ch[pos].val > 0)
				k = ((k + ch[pos].val - 2) % mod + mod) % mod + 1;
			else
				k = ((k + ch[pos].val - 1) % mod + mod) % mod + 1;

			//cout << update(2, 1, n, 1) << endl;
			pos = update(k, 1, n, 1);
			//cout << pos << " " << k << endl;
		}
		printf("%s %d\n", ch[pos].name, factorNum[ix]);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值