poj 2868 Who Gets the Most Candies?

来源:互联网 发布:勇敢的心德莱厄斯淘宝 编辑:程序博客网 时间:2024/04/29 11:25

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 500005int 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]);    }}


0 0
原创粉丝点击