线段树 + 反素数 poj2886
来源:互联网 发布:mac win10 文件共享 编辑:程序博客网 时间:2024/06/13 01:54
关于反素数:摘自此博客:http://magicode.blog.sohu.com/120450550.html
这个题主要用到线段树的思想,每次推算出要出去的人在当前剩下的人中的排位,再用线段树求出其原来的编号,即可算出每次应该出去的人,该人得到的糖果数为f(p)(p为出去的顺序,f(p)为p约数的个数
其实当总人数n确定时,p的值和f(p)的值就确定了,p为小于等于n的最大反素数
新学一个反素数的概念
反素数n,1<=i<n,则f(i)<f(n),即在1-n中,n的约数最多
由于反素数个数不多,这个题可以打表,把1-500000之间的反素数先算出来
反素数有以下两个性质
性质一:一个反素数的质因子必然是从2开始连续的质数.
性质二:p=2^t1*3^t2*5^t3*7^t4.....必然t1>=t2>=t3>=....
这两个性质都比较好证明
所以可以用递归的方法把反素数求出来
代码:
//反素数#include <iostream>#include <cmath>using namespace std;//32位整数的反素数只能由这几个素数构成int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23 }; int bestNum; //反素数__int64 bestSum;//反素数的约数个数//当数为num时,其约数个数为sum,本次对第k个素数的幂进行选取,//幂最高只能选limit, 求比n小的最大的反素数void search(int num, __int64 sum, int k, int limit, int n){ if (k >= 9) return; if (sum > bestSum) { //更新 bestSum = sum; bestNum = num; } else if (bestSum == sum && bestNum > num) //约数个数相同时,选取较小的数 bestNum = num; int i, newNum = num; for (i = 1; i <= limit; i++) //第k个素数取i次方 { newNum *= prime[k]; if (newNum > n) break; search(newNum, sum * (i + 1), k + 1, i, n); //第k+1个素数最多取i次,根据上面的第二条性质 }}int main(){ int n = 500000; cout << (int)log2(n * 1.0) << endl; int i = 0; while (n > 0) { i++; bestNum = 1; bestSum = 1; search(1, 1, 0, (int)log2(n * 1.0), n); cout << "{" << bestNum << ", " << bestSum << "}, "; n = bestNum - 1; } cout << i << endl; return 0;}
题意:输出第p个退出环的人的编号,使得p的约数最多。
解题:p的值为小于n的最大的反素数,因为此时p的约数最多。
#include <iostream>#include <cstdio>using namespace std;#define N 500005//反素数表int antiprime[35][2] = {{498960, 200}, {332640, 192}, {277200, 180}, {221760, 168}, {166320, 160}, {110880, 144},{83160, 128}, {55440, 120}, {50400, 108}, {45360, 100}, {27720, 96}, {25200, 90},{20160, 84}, {15120, 80}, {10080, 72}, {7560, 64}, {5040, 60}, {2520, 48}, {1680, 40},{1260, 36}, {840, 32}, {720, 30}, {360, 24}, {240, 20}, {180, 18}, {120, 16}, {60, 12},{48, 10}, {36, 9}, {24, 8}, {12, 6}, {6, 4}, {4, 3}, {2, 2}, {1, 1} };int sum[N << 2], num[N]; //sum数组存储区间内的人数char name[N][12];void pushUp(int rt){ sum[rt] = 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 (l, m, rt << 1); build (m + 1, r, rt << 1 | 1); pushUp(rt);}void update(int p, int l, int r, int rt){ if (l == r) { sum[rt] = 0; return; } int m = (l + r) >> 1; if (m >= p) update(p, l, m, rt << 1); else update(p, m + 1, r, rt << 1 | 1); pushUp(rt);}int query(int k, int l, int r, int rt){ if (l == r) return l; int m = (l + r) >> 1; if (sum[rt << 1] >= k) return query(k, l, m, rt << 1); else return query(k - sum[rt << 1], m + 1, r, rt << 1 | 1);}int main(){ int i, n, k, pos, p, candy; while (scanf ("%d %d", &n, &k) != EOF) { i = 0; while (n < antiprime[i][0]) i++; p = antiprime[i][0]; candy = antiprime[i][1]; for (i = 1; i <= n; i++) scanf ("\n%s %d", name[i], &num[i]); build (1, n, 1); i = 1; pos = k; //k为人在约瑟夫环中的相对位置,pos为该人在最初的环中的绝对位置 while (i < p) { update (pos, 1, n, 1); //删除当前这个人 //求出下一个人的在约瑟夫环中的相对位置 k += num[pos]; if (num[pos] > 0) k--; //注意:当num[pos] > 0时,pos后面的人的相对位置都要减1 k = (k % sum[1] + sum[1]) % sum[1]; //sum[1]为剩余人的人数 if (k == 0) k = sum[1]; //由相对位置求出绝对位置 pos = query(k, 1, n, 1); i++; } printf ("%s %d\n", name[pos], candy); } 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
- csdn 第三天
- 一个画钟程序,终于做完了,作个记号
- vc++网络安全编程范例(18)-open ssl 实现数字证书编程
- Programming Clojure学习笔记——与Java一起工作
- RLE压缩算法
- 线段树 + 反素数 poj2886
- 2011年最重要的10个开源软件
- 以集成和管理为主要手段的企业报表中心架构设计
- concepts阅读总结3——文件
- 李伟老师给我们带来的第三节实训课
- VC6.0 String的用法
- 查找最大元素
- 推荐6款常用的Java开源报表制作工具
- windows phone 7音频采样探索