您的位置:首页 > 其它

poj 2868 Who Gets the Most Candies?

2014-05-13 19:24 267 查看
http://poj.org/problem?id=2886

题目大意:n 个小孩围城一圈,每个孩子手里都有一张卡片,卡片上面有一个整形数字,当第 k 个孩子离开圈子时,他手里卡片上的数字如果是个整数m, 下一个离开的就是 他左边第m 个孩子,如果是-m ,下一个离开的就是他右边的第m 个孩子。

第 x 个离开的孩子,他会得到糖果f(x)个,f(x) 是 x 的因子的个数,如f(4) = 3;要求得到最多糖果的孩子是谁,以及得到的糖果数。

其实就是求因子数最多的x ,这样我们就会想到,反素数。

反素数: 我们假设f(x) 是x 的因子数,对于所有的 1 <= i < x, 都有f(i) < f (x) ,此时我们就成 x 为反素数。 换句话说就是,所有小于x 的数的因子数都没有x 多。

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define MAXN 500005
int RPrime[]= //反素数
{
    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
};

int fact[]= //反素数约数个数
{
    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
};
struct A
{
    char s[15];
    int num;
}a[MAXN];
int n,k,sum[4*MAXN];
void pushup(int root)
{
    sum[root] = sum[2*root] + sum[2*root+1];
}
void build(int l,int r,int root)
{
    if(l == r)
    {
        sum[root] = 1;
        return ;
    }
    int mid = (l+r)/2;
    build(l,mid,2*root);
    build(mid+1,r,2*root+1);
    pushup(root);
}
int update(int l ,int r,int root,int k)
{
    sum[root]--;
    if(l == r)
        return l;
    int mid = (l+r)/2;
    if(k <= sum[2*root]) update(l,mid,2*root,k);
    else update(mid+1,r,2*root+1,k-sum[2*root]);
}
int main()
{
    while(cin>>n>>k)
    {
        int i,p;
        for(i = 1; i <= n; i++)
        {
            scanf(" %s%d",a[i].s,&a[i].num);
        }
        i = 0;
        while(RPrime[i] <= n)//找到最大的反素数
        {
            i++;
        }
        p = i-1;
        build(1,n,1);
        int tmp = 0;//tmp 表示当前位子
        a[tmp].num = 0;
        for(i = 1; i <= RPrime[p]; i++)
        {
            int mod = sum[1];//mod 表示当前圈子中的全部人数
            if(a[tmp].num > 0)
                k = ((k + a[tmp].num - 2)%mod + mod)%mod + 1;//k 表示第几个人要出去
            else//因为k  是从1 开始的,为了避免k + a[tmp] == 0 的情况,所以要在后面+1,前面-1
                k = ((k + a[tmp].num - 1)%mod + mod)%mod + 1;
            tmp = update(1,n,1,k);//tmp 表示第k 个出去的人的当前位子
        }
        printf("%s %d\n",a[tmp].s,fact[p]);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: