zoukankan      html  css  js  c++  java
  • 【POJ 2886】Who Gets the Most Candies?

    约瑟夫问题的升级版,每次出去的是前一个出去的人位置+手上的数字(正往前,负往后)。第i个出去的人拿的糖是i的约数的个数。求拿糖最多的人和他的糖果数。

    分析

    线段树单点更新,反素数。

    我竟然WA在了反素数少了几个QAQ

    代码

    #include<cstdio>
    #include<cstring>
    #define N 500002
    #define mid int m=l+((r-l)>>1)
    #define lson l,m,node<<1
    #define rson m+1,r,node<<1|1
    using namespace std;
    
    int v[N];
    char name[N][13];
    int n,k;
    int sum[N<<2];
    
    int rprim[50]= {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 nprim[50]= {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};//反素数的约数个数
    
    void build(int l,int r,int node)
    {
        sum[node]=r-l+1;//sum储存这个区间有多少个数
        if(l<r)
        {
            mid;
            build(lson);
            build(rson);
        }
    }
    int out(int l,int r,int node,int k)
    {
        sum[node]--;//这个区间减少一个数
        if(l==r)
            return l;//返回这个减少的数的原始下标
        mid;
        if(k<=sum[node<<1])//要找的第k个数小于等于左半区间的个数
            return out(lson,k);//就递归左子树
        else
            return out(rson,k-sum[node<<1]);//否则就在右子树,且k-左子树的个数
    }
    int main()
    {
        while(~scanf("%d%d",&n,&k))
        {
            memset(name,0,sizeof(name));//清空名字
            for(int i=1; i<=n; i++)
                scanf("%s%d",name[i],&v[i]);
            build(1,n,1);
    
            int tn=n,now,p=0;
            while(rprim[p]<=n)p++;//找出n里最大的反素数
    
            for(int i=1; i<rprim[p-1]; i++)//反素数前的都出队
            {
                now=out(1,n,1,k);//当前出队的序号
                tn--;//剩下的人数
                if (v[now]>0)//向前数
                    k=(k-1+v[now])%tn;//先减去本身这个位置 然后往前v个 再取模
                else
                    k=((k+v[now])%tn+tn)%tn;//直接往后 然后要取模再取模保证正数
                if (k==0) k=tn;//如果刚好是tn 取模会变成0
            }
            now=out(1,n,1,k);//得到第最大的反素数个出队的人的序号
            printf("%s %d
    ",name[now],nprim[p-1]);
        }
        return 0;
    }
  • 相关阅读:
    Windows 7 NVMe补丁(包括官网下载链接)
    最近做的项目的数据处理及可视化小结
    debugging tools for windows 10下载安装问题
    QT安装过程中出现的问题
    Datasnap 中序列化和反序列化
    C# POST multipart/form-data 方式提交数据
    Delphi的前景
    Delphi 禁止重复运行同一程序的方法
    Delphi7 打开工程报错 '找不到指定的模块'&'EOIesysError'
    Delphi7 “cannot Create output File ..inproject1.exe”
  • 原文地址:https://www.cnblogs.com/flipped/p/5202584.html
Copyright © 2011-2022 走看看