题意:有N个人围成一圈,编号从1到N,每个人都有一个卡片,卡片上写了一个数字。若该数字小于0,则从他的从左边开始一直查到该数字的位置(不包括他自己),否则,从右边开始;然后他跳出该循环圈,下一个人是查到的那个人。某人是第m个跳出会得到F(m)个糖果,F(m)为么得因子个数。最后输出谁得到最多糖果的人的姓名和糖果数量。
求F(m)用反素数求。
对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数·
性质一:一个反素数的质因子必然是从2开始连续的
质数.
性质二:p=2^t1*3^t2*5^t3*7^t4.....必然t1>=t2>=t3>=....
因子个数为(t1+1)*(t2+1)*(t3+1)....
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#define LL long long
using namespace std;
bool vis[550000];
//a数组是用init()函数打出的素数表
//因为N为500000,根据反素数的性质,所以最多7个素数就够了
int a[]={2,3,5,7,11,13,17,19,23,29};
int num[550000];
void init(){
memset(vis,false,sizeof(vis));
int m = sqrt(500000+0.5);
for(int i = 2; i <= m; i++){
if(!vis[i]){
printf("%d,",i);
for(int j = i*i; j <= 500000; j += i){
vis[j] = true;
}
}
}
}
void DFS(LL n,int index,int deep,int ans,int limit){
if(n > 500010){
return ;
}
if(deep > 6){
return ;
}
//index为a数组的下标
//deep为深度,最多7次就够了
//ans为n的因子个数
//limit为该素数用的上限。
num[n] = ans;
for(int i = 1,temp = 1; i <= limit; ++i){
temp *= a[index];
DFS(temp*n,index+1,deep+1,ans*(i+1),i);
}
}
int main()
{
//freopen("out.txt","w",stdout);
//init();
memset(vis,0,sizeof(vis));
DFS(1,0,1,1,17);
int mx = 0;
int cnt = 0;
for(int i = 0; i <= 500010; ++i){
if(num[i] > mx){
cnt++;
//printf("%d,",num[i]);
//printf("num[%d] = %d\n",i,num[i]);
mx = num[i];
}
}
cout<<cnt<<endl;
return 0;
}
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#define MAXN 500010
using namespace std;
struct perpon{
char name[20];
int val;
}p[MAXN];
int n,k;
struct node{
int l,r;
int sum;
}a[MAXN<<2];
int Max;
//打表得到的
int aaa[36]={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 bbb[36]={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,200};
void pushup(int index){
a[index].sum = a[index<<1].sum+a[index<<1|1].sum;
}
void build(int l,int r,int index){
a[index].l = l;
a[index].r = r;
if(l == r){
a[index].sum = 1;
return ;
}
int mid = (l+r)>>1;
build(l,mid,index<<1);
build(mid+1,r,index<<1|1);
pushup(index);
}
//查询原始坐标
int updata(int index,int k){
a[index].sum--;
if(a[index].l == a[index].r){
return a[index].l;
}
int temp;
if(k <= a[index<<1].sum){
temp = updata(index<<1,k);
}
else{
temp = updata(index<<1|1,k-a[index<<1].sum);
}
pushup(index);
return temp;
}
int judge(){
for(int i = 0; i < 36; ++i){
if(n < aaa[i]){
Max = bbb[i-1];
return aaa[i-1];
}
}
}
int main(){
//freopen("out.txt","w",stdout);
while(~scanf("%d %d",&n,&k)){
for(int i = 0; i < n; i++){
scanf("%s %d",p[i+1].name,&p[i+1].val);
}
build(1,n,1);
int num = n-1;
int cnt = judge();
// k 为 循环圈里的第K个人
//num 为 循环圈里的人数-1
//cnt 为 1~n中 因子数最多的 数
while(--cnt){
int index = updata(1,k);
//index为原始坐标
int z = abs(p[index].val)%num;
if(z == 0){
z = num;
}
if(p[index].val < 0){
if(z > k-1){
k = abs(z-num)+k;
}
else{
k = abs(z-k);
}
}
else{
k = (z+k-1)%num;
if(k == 0){
k = num;
}
}
num--;
}
k = updata(1,k);
//cout<<"--------"<<endl;
//cout<<k<<endl;
printf("%s %d\n",p[k].name,Max);
}
return 0;
}
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#define LL long long
using namespace std;
bool vis[550000];
//a数组是用init()函数打出的素数表
//因为N为500000,根据反素数的性质,所以最多7个素数就够了
int a[]={2,3,5,7,11,13,17,19,23,29};
int num[550000];
void init(){
memset(vis,false,sizeof(vis));
int m = sqrt(500000+0.5);
for(int i = 2; i <= m; i++){
if(!vis[i]){
printf("%d,",i);
for(int j = i*i; j <= 500000; j += i){
vis[j] = true;
}
}
}
}
void DFS(LL n,int index,int deep,int ans,int limit){
if(n > 500010){
return ;
}
if(deep > 6){
return ;
}
//index为a数组的下标
//deep为深度,最多7次就够了
//ans为n的因子个数
//limit为该素数用的上限。
num[n] = ans;
for(int i = 1,temp = 1; i <= limit; ++i){
temp *= a[index];
DFS(temp*n,index+1,deep+1,ans*(i+1),i);
}
}
int main()
{
//freopen("out.txt","w",stdout);
//init();
memset(vis,0,sizeof(vis));
DFS(1,0,1,1,17);
int mx = 0;
int cnt = 0;
for(int i = 0; i <= 500010; ++i){
if(num[i] > mx){
cnt++;
//printf("%d,",num[i]);
//printf("num[%d] = %d\n",i,num[i]);
mx = num[i];
}
}
cout<<cnt<<endl;
return 0;
}
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#define MAXN 500010
using namespace std;
struct perpon{
char name[20];
int val;
}p[MAXN];
int n,k;
struct node{
int l,r;
int sum;
}a[MAXN<<2];
int Max;
//打表得到的
int aaa[36]={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 bbb[36]={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,200};
void pushup(int index){
a[index].sum = a[index<<1].sum+a[index<<1|1].sum;
}
void build(int l,int r,int index){
a[index].l = l;
a[index].r = r;
if(l == r){
a[index].sum = 1;
return ;
}
int mid = (l+r)>>1;
build(l,mid,index<<1);
build(mid+1,r,index<<1|1);
pushup(index);
}
//查询原始坐标
int updata(int index,int k){
a[index].sum--;
if(a[index].l == a[index].r){
return a[index].l;
}
int temp;
if(k <= a[index<<1].sum){
temp = updata(index<<1,k);
}
else{
temp = updata(index<<1|1,k-a[index<<1].sum);
}
pushup(index);
return temp;
}
int judge(){
for(int i = 0; i < 36; ++i){
if(n < aaa[i]){
Max = bbb[i-1];
return aaa[i-1];
}
}
}
int main(){
//freopen("out.txt","w",stdout);
while(~scanf("%d %d",&n,&k)){
for(int i = 0; i < n; i++){
scanf("%s %d",p[i+1].name,&p[i+1].val);
}
build(1,n,1);
int num = n-1;
int cnt = judge();
// k 为 循环圈里的第K个人
//num 为 循环圈里的人数-1
//cnt 为 1~n中 因子数最多的 数
while(--cnt){
int index = updata(1,k);
//index为原始坐标
int z = abs(p[index].val)%num;
if(z == 0){
z = num;
}
if(p[index].val < 0){
if(z > k-1){
k = abs(z-num)+k;
}
else{
k = abs(z-k);
}
}
else{
k = (z+k-1)%num;
if(k == 0){
k = num;
}
}
num--;
}
k = updata(1,k);
//cout<<"--------"<<endl;
//cout<<k<<endl;
printf("%s %d\n",p[k].name,Max);
}
return 0;
}