题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5860
#include<bits/stdc++.h>
using namespace std;#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<ll,ll>
#define mk(x,y) make_pair(x,y)
const int maxn =4e6+5;
const int mod=998244353;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:n个人围成一圈,每一轮
按编号1,1+k,1+2k,...这样的顺序排除人,
要求输出排除人的原本的编号序列。题目分析:动态规划分析,
把状态分为轮数和当前轮数的第几个人,
分别用s和t数组表示。s表示i号人在s[i]轮被去除,
t表示i号人在当前轮第t[i]个被去除,再思考状态转移关系,
找找规律T_T,可以观察第二轮和第一轮的关系:
s[i]=i%k?s[i-i/k-1]:1;
t[i]=i%k?t[i-i/k-1]:i/k+1。
在转移的过程中我们累加计数每一轮的编号数量,
再对计数数组求前缀和,这样就可以把每个位置映射成其第几个出列的了,输出答案即可。时间复杂度:O(n)。
*/
int n,k,q,tot;
int s[maxn],t[maxn];
int ans[maxn],sum[maxn];
int main(){int tt;scanf("%d",&tt);while(tt--){scanf("%d%d%d",&n,&k,&q);mst(sum,0),tot=1;rep(i,0,n){if(i%k){s[i]=s[i-i/k-1]+1,t[i]=t[i-i/k-1];++sum[s[i]];tot=max(tot,s[i]);}else{s[i]=1,t[i]=i/k+1;sum[1]++;}}rep(i,1,tot+1) sum[i]+=sum[i-1];rep(i,0,n) ans[sum[s[i]-1]+t[i]]=i+1;while(q--){scanf("%d",&k);printf("%d\n",ans[k]);}}return 0;
}