点击打开链接
题意:n个熊孩子按顺时针排列,每个人受伤都有一张牌,牌上有一个数字,从第k个孩子开始出队,出队的熊孩子卡上数字是K,则顺时针第k人是下一个出队的,负数则逆时针,第P个出队的会得到的糖果数是p的因子个数,输出得到最多糖果的人和他的糖果数,如果有多个,则输出最先出队的。
思路:用线段树来存储整个区间中的剩余人的个数、然后用反素数来找因子数最多的人的出队的序号。
反素数就是 对 x来说约束个数 G(x),如果 对于 i
则称x为反素数。
对于 n 个孩子 ,最后拿到最多的糖果就是 小于等于 n 的最大 反素数。但是 是哪个孩子并不知道,那么就要进行模拟
对于 k 位置的 孩子,他的 数字是 +num 那么因为他自己本身是要被踢走的,所以相对位置 为k= k+num-1
如果数字是 -num,那么按正着数就没影响,k=k-num。线段树存储当前区间共有多少个人,每一次找到第k (前面有k-1个)个孩子,经过的区间都要 -1,然后记录被踢走的孩子编号
///反素数打表
void Solve(){
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++){
ans[i]++;
for(int j=2*i;j<=n;j+=i)
ans[j]++;
}
int max=ans[1];
id=1;
for(int i=2;i<=n;i++) //找出第几个人跳出获得的糖最多
if(ans[i]>max){
max=ans[i];
id=i;
}
}
#include
#include
#include
#include
#include
#include
#define LL long long
#define INF 0x3f3f3f3f
#define lson L,mid,ind<<1
#define rson mid+1,R,ind<<1|1
using namespace std;
const int N=2010000;
int sum[N];
void pushup(int ind){
sum[ind]=sum[ind<<1]+sum[ind<<1|1];
}
void build(int L,int R,int ind){
sum[ind]=R-L+1;
if(L==R){
return ;
}
int mid=L+(R-L)/2;
build(lson);
build(rson);
}
int update(int d,int L,int R,int ind){
sum[ind]--;
if(L==R){
return L;
}
int mid=L+(R-L)/2;
if(d<=sum[ind<<1]) return update(d,lson);
else return update(d-sum[ind<<1],rson);
}
bool vis[N];
int fprim[N],num;
void init(){
num=0;
memset(fprim,0,sizeof(fprim));
for(int i=1;i<=500001;i++){
fprim[i]++;
for(int j=i*2;j<=500001;j+=i){
fprim[j]++;
}
}
}
int a[N][20],d[N];
int main(){
init();
int n,k;
while(~scanf("%d%d",&n,&k)){
build(1,n,1);
int Max=1;
int id=1;
for(int i=1;i<=n;i++){
if(fprim[i]>Max){Max=fprim[i];
id = i;
}
}
// cout<0){
k=((k-1+d[pos]-1)%huan+huan)%huan+1;
}
else k=((k-1+d[pos])%huan+huan)%huan+1;
pos=update(k,1,n,1);
huan--;
}
// cout<
#include
#include
#include
#include
#include
#include
#include