题目链接:
题目意思:
编号为1-n的n个人逆时针围成一圈玩游戏,每个人有一个非零的数的卡片,开始从第k个人开始,一次出圈,当第i个人出圈时,如果他的卡片上的数正数p,则他左边的第p个人下个出圈,如果他卡片上的数是负数p,则他右边的第p个人下个出圈。当第i个人出圈时,他获奖励是F(i),F(i)为i的正约数的个数。求获得的最大的奖励是哪个人,及奖励数。
解题思路:
1、反素数的应用。设F(i)为i的正约数个数,若对任意的x<i,有F(x)<F(i),则i为反素数。找出不超过n的第一个最大的反素数即可。
打印反素数代码:
#include using namespace std;__int64 bestnum;__int64 bestsum;__int64 n;__int64 prime[10]={2,3,5,7,11,13,17,19,23};__int64 limit[10];void creatLimit(__int64 n){memset(limit,0,sizeof(limit));__int64 i,rn;for(i=0;i<=8;i++){ rn=n; while(rn>prime[i]) { limit[i]++; rn/=prime[i]; }}}void creatRPrime(__int64 num,__int64 k,__int64 sum,__int64 limit) //num:数 sum: 因子数{__int64 i,p;if(num>n)return;if(sum>bestsum){ bestsum=sum; bestnum=num;}else{ if(sum==bestsum && num 8) return;p=1;for(i=1;i<=limit;i++){ p*=prime[k]; creatRPrime(num*p,k+1,sum*(i+1),i);}}__int64 log2(__int64 n) //求大于等于log2(n)的最小整数{__int64 i = 0;__int64 p = 1;while(p
2、用一颗线段树维护原始区间内剩下的人的个数,从而找到顺序出圈的人的原始序号。注意借用前面的人在上一区间的标号位置,这点很关键。
关键:上一原始位置与下一顺序位置的关系。
详见代码:
#include #include #include #include #include #include #include #include #include