poj2886线段树+反素数
来源:互联网 发布:淘宝睡衣模特是谁 编辑:程序博客网 时间:2024/05/16 19:08
8<---------------------------------------------------
题意:
N个小朋友围一圈。
指定一个人为起始点之后,此人出圈。
按照这个人手中卡片的数字找到下一个人,下一个人出圈。
。。。
直到最后一个人出圈。
8<--------------------------------------------
思路:
一:当期指定的人在第 K 个位置,他出圈后,找到下一个人在剩下的人中的位置 next_k。
if(A >= 0) next_k = (k-1+A-1)%n + 1; else next_k = ((k-1+A)%n + n)%n + 1;
二:利用线段树树状数组求出接下来出圈的人原来的所在的位置。
以此可以求得第 P 个除圈的人。
三:题目描述最后一句说 F( x )为 x 的约数的个数。求这一组数的最大的 F(x),输出x, 以及相应的人名。
此处需要反素数表。
利用反素数相关知识,求出小于 N 的最大反素数 F(X), 得到X。
利用思路二可以求出第F(X)个出圈的人。
输出人名和x。
8<-------------------------------------------
刚开始不知道用到反素数,只暴力球了各个数的因子个数,无数个WA 和 超时, 错误百出。
搜了一下题解,用的反素数打表。
第一次接触反素数,了解了一下发现维基 和 百度说法不一。
不过总算知道是什么了。
啊, 第一次纯手写线段树不用看模板,脑海中的线段树模板有区间查询,这里是根据一个特定的值查询,稍微改了一下就好使了。
(呃。。。。我费了好长时间写这个查询啊……甚至还写了二级查询……慢慢调才搞出来简短的这个……当然代码里看不出来啦……弱弱仍需努力……)
8<---------------------------------------------
/*poj2886线段树*/#include<stdio.h>#include<iostream>#include<string.h>using namespace std;#define lson l, m, rt<<1#define rson m+1, r, rt<<1|1#define maxn 500040char str[maxn][10];int A[maxn];int sum[maxn<<2];int n, k;int operate(int a, int b){ return a+b;}void PushUp(int rt){ sum[rt] = operate(sum[rt<<1], sum[rt<<1|1]);}void build(int l, int r, int rt){ if(l == r){ sum[rt] = 1; return ; } int m = (l+r)>>1; build(lson); build(rson); PushUp(rt);}void Update(int p, int add, int l, int r, int rt){ if(l == r){ sum[rt] = add; return ; } int m = (l+r)>>1; if(p <= m) Update(p, add, lson); else if(p>m) Update(p, add, rson); PushUp(rt);}int Query(int k, int l, int r, int rt){ if(l==r && k == 1 && sum[rt] == k){ return l; } int m = (l+r)>>1; int ret = 0; if(sum[rt<<1] < k){ ret = Query(k-sum[rt<<1], rson); }else if(sum[rt<<1] >= k){ ret = Query(k, lson); } return ret;}int main(){ //freopen("in.txt", "r", stdin); int maxp_pos, maxp; int a[37]={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,500001}; int b[37]={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,1314521}; while(scanf("%d %d", &n, &k) != EOF){ memset(sum, 0, sizeof(sum)); for(int i=1; i<=n; i++){ scanf("%s %d", str[i], &A[i]); } build(1, n, 1); int i=0; while(a[i] <= n) i++; int p = a[i-1]; maxp = b[i-1]; int cnt = 1, next_k = k, tmp = k; int tmp_n = n; while(cnt<n){ cnt++; Update(tmp, 0, 1, n, 1); tmp_n --; if(A[tmp]>=0) next_k = (next_k-1+A[tmp]-1)%tmp_n+1; else next_k = ((next_k-1+A[tmp])%tmp_n+tmp_n)%tmp_n + 1; tmp = Query(next_k, 1, n, 1); if(cnt == p) maxp_pos = tmp; } printf("%s %d\n", str[maxp_pos], maxp); } return 0;}
- 线段树 + 反素数 poj2886
- poj2886 线段树+反素数
- poj2886线段树+反素数
- poj2886反素数与线段树
- POJ2886(反素数+约瑟夫环+线段树)#nobody
- poj2886--Who Gets the Most Candies?(线段树+反素数)
- 【POJ2886】Who Gets the Most Candies?-线段树+反素数
- poj2886 Who Gets the Most Candies?反素数+线段树
- poj2886 线段树单点修改+反素数(喵?)
- POJ2886 Who Gets the Most Candies? 【线段树】+【单点更新】+【模拟】+【反素数】
- poj2886 Who Gets the Most Candies?(反素数 + 线段树)
- POJ2886 Who Gets the Most Candies? 线段树单点更新+反素数
- POJ2886 Who Gets the Most Candies?(反素数+线段树模拟约瑟夫环)
- [POJ2886] 谁得到最多糖果 - 反质数+线段树
- poj2886 线段树
- POJ2886(线段树)
- POJ2886-Who Gets the Most Candies?-模拟约瑟夫环+反素数表(线段树上二分+爆搜打表)
- 线段树(3) poj2886
- c++中的list用法
- Singletons in Cocoa, are they evil?
- 遍历矩阵的n^m种情况的解决办法
- 黑马程序员----C#中的流程控制语句之循环语句
- iOS - 判断程序是否是第一次启动 & 进程延迟
- poj2886线段树+反素数
- 自定义调试信息的输出
- 按位运算符
- Ubuntu到12.04花屏位移解决办法
- git 实际使用记录
- 关于C-free工具中C调试出现DOS窗口闪过问题
- nefu 84 http://acm.nefu.edu.cn/test/problemshow.php?problem_id=84
- 热门iOS开发资源精选
- IE11“请勿追踪”功能改进 用户权限扩大