poj 2886 没啥,线段树基础应用,纪念一下队长教的打素数的方法
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 500010;
struct NN
{
char s[20];
int num;
} ch[maxn];
int prim[maxn], plen;
bool vis[maxn];
long long cc[maxn];
void mklist()
{
plen = 0;
memset(prim, false, sizeof(prim));
for(int i = 2; i * i <= maxn; ++i)
{
if(!prim[i])
{
for(int j = i; j * i <= maxn; ++j)
{
if(!prim[i * j])
prim[i * j] = i;
}
}
}
}
long long split(int x)
{
long long ans = 1;
int cur = x;
if(x == 1) return 1;
int tmp = prim[cur];
while(prim[cur] != 0)
{
int cnt = 0;
while(cur % tmp == 0)
{
++cnt;
cur /= tmp;
}
ans *= cnt + 1;
tmp = prim[cur];
}
if(cur != 1)
ans *= 2;
return ans;
}
struct node
{
int l, r, mid;
int count;
node()
{
count = 0;
}
} seg[3 * maxn];
void build(int l, int r, int num)
{
seg[num].l = l;
seg[num].r = r;
seg[num].mid = (l + r) >> 1;
if(l + 1 == r)
{
seg[num].count = 1;
return ;
}
build(l, seg[num].mid, num << 1);
build(seg[num].mid, r, num << 1 | 1);
seg[num].count = seg[num << 1].count + seg[num << 1 | 1].count;
}
int search(int k, int num)
{
if(seg[num].l + 1 == seg[num].r)
{
seg[num].count--;
return seg[num].l;
}
seg[num].count--;
if(k <= seg[num << 1].count)
{
return search(k, num << 1);
}
else
{
return search(k - seg[num << 1].count, num << 1 | 1);
}
}
int n, k;
int main()
{
// freopen("in.txt", "r", stdin);
mklist();
while(scanf("%d%d", &n, &k) != EOF)
{
for(int i = 1; i <= n; ++i)
{
scanf("%s%d", ch[i].s, &ch[i].num);
}
int res = 1;
int mac = 1;
for(int i = n / 2 + 1; i <= n; ++i)
{
int tmp = split(i);
if(res < tmp)
{
res = tmp;
mac = i;
}
}
build(1, n + 1, 1);
int st = k;
int t = search(k, 1);
if(mac == 1)
{
printf("%s %d\n", ch[t].s, res);
continue;
}
int ans = t;
for(int i = 2; i <= mac; ++i)
{
if(ch[ans].num > 0)
{
st = (st + ch[ans].num - 1) % seg[1].count;
if(st == 0)
st = seg[1].count;
ans = search(st, 1);
}
else
{
st = (st + ch[ans].num) % seg[1].count;
if(st <= 0)
st += seg[1].count;
ans = search(st, 1);
}
}
printf("%s %d\n", ch[ans].s, res);
}
return 0;
}