POJ 2886 Who Gets the Most Candies?(线段树 + 约瑟夫环 + 反素数)
2013-10-26 20:45
537 查看
线段树 + 约瑟夫环 + 反素数
题目连接
题意 : N个人顺时针围成一圈,每个人有一张卡片,轮到某个人的时候进行以下操作 :1 , 这个人退出这个圈。2,如果这个人的卡片上的数字是正数X则向右数X个位置,otherwise向左数(-X)个位置。3被数到的那个人执行相同操作,直至没有人为止。4,如果原来的那个人是第K个,那么他将会获得P(K)颗糖。 注 : P(k)表示k的不同约数数量(可以是1或者本身)。
思路 : 首先给定一个数N的话可以利用反素数打表很快求出到底是第M个执行操作获得的Candies最多。 然后约瑟夫环模拟寻找第M个人是谁。另外可以用线段树保存绝对位置下标和执行寻找相对位置下标这一操作。
注意 :是卡片数字是正的往右数喔 。
题目连接
题意 : N个人顺时针围成一圈,每个人有一张卡片,轮到某个人的时候进行以下操作 :1 , 这个人退出这个圈。2,如果这个人的卡片上的数字是正数X则向右数X个位置,otherwise向左数(-X)个位置。3被数到的那个人执行相同操作,直至没有人为止。4,如果原来的那个人是第K个,那么他将会获得P(K)颗糖。 注 : P(k)表示k的不同约数数量(可以是1或者本身)。
思路 : 首先给定一个数N的话可以利用反素数打表很快求出到底是第M个执行操作获得的Candies最多。 然后约瑟夫环模拟寻找第M个人是谁。另外可以用线段树保存绝对位置下标和执行寻找相对位置下标这一操作。
注意 :是卡片数字是正的往右数喔 。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 500005; #define lson rt<<1, l, mid #define rson rt<<1|1, mid+1, r int max(int a, int b){return a > b ? a : b;} int ans[maxn][2]; char name[maxn][12]; int cov[maxn<<2], aa[maxn], n, k; int inprime[40] = { 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 }, MaxSize = 35, fg[40]; void pushup(int rt) { cov[rt] = cov[rt<<1] + cov[rt<<1|1]; } void build(int rt, int l, int r) { if (l == r) { cov[rt] = 1; return ; } int mid = (l + r) >> 1; build(lson); build(rson); pushup(rt); } void update(int rt, int l, int r, int pos) { if (l == r) { cov[rt] = 0; return ; } int mid = (l + r) >> 1; int lv = cov[rt<<1]; if (pos <= lv)update(lson, pos); else update(rson, pos-lv); pushup(rt); } int query(int rt, int l, int r, int pos) { if (l == r) { return l; } int mid = (l + r) >> 1, lv = cov[rt<<1]; if (pos <= lv)return query(lson, pos); else return query(rson, pos-lv); } int ysf(int sx, int Mx, int num) { if (num == 2)return 1; int res; if (Mx <= 0) { Mx = -Mx; if (Mx < sx)return sx - Mx; if (Mx == sx)return num - 1; Mx -= (sx-1); res = (Mx - 1) % (num - 1) + 1; return num - res; } else { res = Mx - (num - sx); return (res + num - 2) % (num - 1) + 1; } } void solve() { build(1, 1, n); int kk = k, e = k, m = n; for (int i = 2; i <= ans [0]; i++) { update(1, 1, n, kk); kk = ysf(kk, aa[e], m); e = query(1, 1, n, kk); m--; } printf("%s %d\n", name[e], ans [1]); } int get(int x) { int cnt = 0; for (int i = 1; i*i <= x; i++)if (x % i == 0) { cnt++; if (x/i != i)cnt++; } return cnt; } void init() { int i; memset(ans, 0, sizeof(ans)); for (i = 0; i < MaxSize; i++) { fg[i] = get(inprime[i]); ans[inprime[i]][0] = inprime[i]; ans[inprime[i]][1] = fg[i]; } int Maxfg = 0, Maxv = 0; for (i = 1; i <= maxn-1; i++) { Maxv = ans[i][0] = max(ans[i][0], Maxv); Maxfg = ans[i][1] = max(ans[i][1], Maxfg); } } int main() { int i; init(); while (scanf("%d%d", &n, &k) == 2) { for (i = 1; i <= n; i++) scanf("%s%d", name[i], &aa[i]); solve(); } return 0; }
相关文章推荐
- poj 2886 Who Gets the Most Candies?(线段树单点更新模拟约瑟夫环)
- poj 2886 Who Gets the Most Candies?(线段树、反素数)
- poj 2886 Who Gets the Most Candies?(线段树单点更新+反素数)真难。。。
- POJ 2886 Who Gets the Most Candies(线段树模拟约瑟夫环)
- poj 2886 Who Gets the Most Candies?(线段树和反素数)
- [poj 2886] Who Gets the Most Candies[线段树][约瑟夫环][反素数]
- POJ 2886 Who Gets the Most Candies? (高合成数&用线段树维护约瑟夫环)
- POJ 2886 Who Gets the Most Candies?(线段树模拟约瑟夫环,高合成数)
- POJ 2886 Who Gets the Most Candies? (线段树模拟约瑟夫环)
- POJ 2886 Who Gets the Most Candies?(线段树单点更新+反素数)
- poj2886 Who Gets the Most Candies? 线段树加反素数
- POJ 2886 Who Gets the Most Candies? (线段树 约瑟夫环问题变种)
- poj 2886 Who Gets the Most Candies? 【线段树单点更新 + 反素数】
- POJ 2886 Who Gets the Most Candies? (线段树)
- POJ 2886 Who Gets the Most Candies? 线段树
- POJ 2886 Who Gets the Most Candies?(单点更新 + 约瑟夫环)
- POJ-2886 Who Gets the Most Candies? 线段树 + 反素数
- POJ 2886 Who Gets the Most Candies? (线段树,单点更新)
- POJ 2886 Who Gets the Most Candies?(线段树)
- POJ - 2886 Who Gets the Most Candies?(线段树)