poj 2886 反素数+约瑟夫环线段树单点更新

来源:互联网 发布:淘宝产品市场分析报告 编辑:程序博客网 时间:2024/04/19 23:10

题意:

有n(5*10^5)只小朋友做游戏,每个人手上有一张卡片,上面记录着一个非零的数val。

现在他们按照1~n坐成一个环。

然后游戏从第k只小朋友开始,他先跳出这个圈,然后如果他手上的val为正,则下一个小朋友的位置就是他当前位置+val;

相反的,如果他手上的val为负,则下一个小朋友的位置就是他当前位置-val。

现在,第p次的小朋友跳出圈圈的时候他会获得f(p)个糖果,f(p)的定义是p的因子数。

然后问,哪个小朋友出圈时能够得到最多的糖果,输出他的名字,并且输出糖果数。


解析:

无从下手啊。。。

所以从f(p)处下手,f(p)咋一看是确定的值,也就是说,可以确定是第几个小朋友出圈获得最多的糖果。

这个f(p)就是反素数,而他获得的糖果数就是当前这个反素数对应的因子个数。

关于反素数看上一篇。

这样就好办了,因为确定了p,所以只要模拟整个过程,然后确定第p次出来的小朋友是在原来的哪个位置就好了。

用线段树来维护这个游戏,线段树里保存的是当前的小朋友的个数,每当跳出一个小朋友,就更新当前的树,并返回当前小朋友原来的位置lo,就行了。

蛋疼的地方是做还模的时候会模出0,所以模拟的时候。。。。

附带讨论区里的测试数据。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <set>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 500000 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int antiprime[]= {0,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};int factorNum[]= {0,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};struct People{    char name[20];    int val;} people[maxn];int sum[maxn << 2];void pushup(int rt){    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];}void build(int lo, int hi, int rt){    if (lo == hi)    {        sum[rt] = 1;        return ;    }    int mi = (lo + hi) >> 1;    build(lson);    build(rson);    pushup(rt);}int update(int k, int lo, int hi, int rt){    sum[rt]--;    if (lo == hi)        return lo;    int mi = (lo + hi) >> 1;    if (k <= sum[rt << 1])        return update(k, lson);    else        return update(k - sum[rt << 1], rson);}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int n, k;    while (~scanf("%d%d", &n, &k))    {        for (int i = 1; i <= n; i++)        {            scanf("%s%d", people[i].name, &people[i].val);        }        ///        int t = 1;        while (antiprime[t] <= n)            t++;        t--;        int p = antiprime[t];//第p个小朋友所得到的factorNum是最大的。        ///        build(1, n, 1);        int pos = 0;        //模拟p次就好了        while (p--)        {            if (0 < people[pos].val)                k = (k - 1 + people[pos].val - 1) % sum[1] + 1;            else if (people[pos].val < 0)                k = ((k - 1 + people[pos].val) % sum[1] + sum[1]) % sum[1] + 1;            pos = update(k, 1, n, 1);        }        printf("%s %d\n", people[pos].name, factorNum[t]);    }    return 0;}///input/*2 15705 -2446416827 232812 1292 -15318716 -174212 117035 2629923811 -287034 132662 2764412859 2003727529 97413035 -123162 115890 -2380515350 243706 34966 -1184026308 -1393124626 -3243921538 553722929 -208231115 48332 126924 287455829 -62706 123655 2476712052 -403116941 -11503430 -1396618007 3019112287 154572 127506 -2494629168 -164132 127595 -648324350 36022 18281 -244841999 -532 117807 -224836617 143105 122798 3155611008 622414989 -3260920485 -319530523 143434 115281 -1479828009 2079823622 204726038 -122922 12634 1620220328 -200552 131998 -2188110021 -186513 126869 -2100313401 1468816423 152552 14169 -3093217189 -257216 130145 95123753 -2171816279 1242312529 -1668719866 1743723195 1932 131316 -1170112263 57862 128321 2775627982 -236465 312044 1046626439 2629226154 2002420649 -47454474 -83133 14414 2647729334 -2582420159 -243722 117192 26688480 31025 113061 2997227432 3100322725 27593142 849213064 -312862 125760 197117285 -46672 126302 -226584678 224663 11926 3106032170 -475730227 95766 12625 1447431928 56296902 2852024596 -12310195 132618260 12642 129790 2152021763 -30188*////output/*16827 218716 223811 212859 315350 221538 45829 23430 429168 224350 21999 26617 214989 36038 320328 210021 216423 217189 219866 412263 227982 24474 329334 28480 2142 37285 24678 230227 224596 421763 2*/


0 0
原创粉丝点击