这个题的数据量一看就是个数学题。。。然后就找啊找啊找规律!


一开始走错了方向,因为k=2

然后呢,找到了一个规律:(只对k=2适合)

第一轮的删掉的数:x%k=0

第二轮的删掉的数:x%k^2=k

第三轮的删掉的数:x%k^3=k^2

然后发现……

只对k=2适合

还是贴个程序纪念一下错误的数学思路吧


#include<bits/stdc++.h>
using namespace std;

#define LL __int64
LL calc(LL n,LL mod,LL left){
    LL x=n/mod;
    LL y=(n-(n/mod)*mod)>=left?1:0;
    return x+y;
}

int main(){
    //printf("%d\n",calc(24,2,1));
    //printf("%d\n",calc(24,4,2));
    //printf("%d\n",calc(24,8,4));
    //printf("%d\n",calc(24,16,8));
    //printf("%d\n",calc(24,32,16));
    //freopen("input.txt","r",stdin);
    int t;
    LL n,k,q;
    scanf("%d",&t);
    while(t--){
        scanf("%I64d%I64d%I64d",&n,&k,&q);
        LL mod,left,temp,x,thistime,num;
        while(q--){
            mod=1;left=0;
            thistime=temp=0;
            scanf("%I64d",&x);
            while(temp<x){
                left=mod;
                mod=mod*k;
                thistime=calc(n,mod,left);
                temp+=thistime;
            }
            num=thistime+x-temp-1;
            printf("%I64d\n",left+num*mod);
        }
    }
    return 0;
}

这个题的正确思路还是应该去打表

s【i】:i这个数是第几轮被删除的

t【i】:i这个数,在第s【i】轮中是第几个被删除的

如果知道这两个值,我们就可以打表了

首先分析第一轮,删去的都是%k为1的数

那么我们变成0~n-1,那么都是整除k的值

所以,如果不整除k呢,就可以往后放(相当于递推)

那么,在之前,删除了多少个数(相当于第一轮删除之后,原来的第i个值,放在了新数列的哪个位置)

顺着这个思路想,就得到了一个递推(说是DP也行)

代码如下:

#include<bits/stdc++.h>
using namespace std;

const int maxn=3e6+50;
int s[maxn],t[maxn],sum[maxn],ans[maxn],tot;

int main(){
    //freopen("input.txt","r",stdin);
    int T,n,k,q,i,j;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&k,&q);
        memset(s,0,sizeof(s));
        memset(t,0,sizeof(t));
        memset(sum,0,sizeof(sum));
        memset(ans,0,sizeof(ans));
        tot=1;
        for(i=0;i<n;i++)
        if (i%k==0){
            s[i]=1;t[i]=i/k+1;sum[1]++;
            //ans[sum[1]]=i+1;
        }
        else{
            j=i-i/k-1;
            s[i]=s[j]+1;
            t[i]=t[j];
            sum[s[i]]++;
            tot=max(tot,s[i]);
        }
        for(int i=1;i<=tot;i++) sum[i]=sum[i]+sum[i-1];
        for(int i=0;i<n;i++)
            ans[sum[s[i]-1]+t[i]]=i+1;
        while(q--){
            scanf("%d",&k);
            printf("%d\n",ans[k]);
        }
    }
    return 0;
}