poj 2886Who Gets the Most Candies?

http://poj.org/problem?id=2886

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <algorithm>

 4 #define maxn 500100

 5 using namespace std;

 6 

 7 typedef long long ll;

 8 const int prime[16]= {1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};

 9 int n,k;

10 struct node

11 {

12     int l,r,num;

13 } tree[maxn*3];

14 

15 ll maxsum,bestnum;

16 char name[maxn][110];

17 int a[maxn];

18 

19 void getantiprime(ll num, ll k,ll sum,int limit)

20 {

21      //num:当前枚举到的数,k:枚举到的第k大的质因子;sum:该数的约数个数;limit:质因子个数上限;

22     int i;

23     ll temp;

24     if(sum > maxsum)

25     {

26         maxsum = sum;

27         bestnum = num; //如果约数个数更多,将最优解更新为当前数;

28     }

29     if(sum==maxsum && bestnum > num)

30         bestnum = num; //如果约数个数相同,将最优解更新为较小的数;

31     if(k > 15)

32         return;

33     temp = num;

34     for(i=1; i<=limit; i++) //开始枚举每个质因子的个数;

35     {

36         if(temp*prime[k] > n)

37             break;

38         temp = temp * prime[k]; //累乘到当前数;

39         getantiprime(temp, k+1, sum*(i+1), i); //继续下一步搜索;

40     }

41 }

42 

43 void build(int i,int l,int r)//建树

44 {

45     tree[i].num=r-l+1;

46     tree[i].l=l;

47     tree[i].r=r;

48     if(l<r)

49     {

50         int mid=(l+r)/2;

51         build(i+i,l,mid);

52         build(i+i+1,mid+1,r);

53     }

54 }

55 

56 int search1(int num,int i)//查找原始序号

57 {

58     tree[i].num--;

59     if(tree[i].l==tree[i].r)

60     {

61         return tree[i].l;

62     }

63     if(num<=tree[i+i].num)

64         return search1(num,i+i);

65     return search1(num-tree[i+i].num,i+i+1);

66 }

67 

68 int main()

69 {

70     while(scanf("%d%d",&n,&k)!=EOF)

71     {

72         getantiprime(1,1,1,50);//找到n以内反素数最大的;

73         build(1,1,n);

74         for(int i=1; i<=n; i++)

75         {

76             scanf("%s %d",name[i],&a[i]);

77         }

78         int id;

79         for(int i=0; i<bestnum; i++)//约瑟夫原理

80         {

81             n--;

82             id=search1(k,1);

83             if(n==0) break;

84             if(a[id]>0)

85                 k=(k-1+a[id]-1)%n+1;

86             else

87                 k=((k-1+a[id])%n+n)%n+1;

88         }

89         printf("%s %lld\n",name[id],maxsum);

90     }

91     return 0;

92 }
View Code

 

你可能感兴趣的:(get)