打表找规律可以发现答案是一段一段连续的区间
用类似于汉诺塔的方法可以推出小球i的通项公式
具体的,第一个球的答案为不为3的倍数的数
第二个球的答案为为3的倍数的数但不为9的倍数的数
第二个球的答案为为9的倍数的数但不为27的倍数的数
类推下去,高精度算个答案就完了
Code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
struct gj{
int n;
int a[505];
gj(){n=0;memset(a,0,sizeof(a));}
inline gj operator + (const gj x)const{
gj res;res.n=max(n,x.n);
for(int i=1;i<=res.n;i++){
res.a[i]+=x.a[i]+a[i];
if(res.a[i]>=10) res.a[i]-=10,res.a[i+1]++;
}
if(res.a[res.n+1]) res.n++;
return res;
}
inline gj operator / (const ll &b)const{
ll ans=0;gj res;res.n=n;
for(int i=res.n;i;i--){
ans=ans*10+a[i];
if(ans>=b) res.a[i]=ans/b,ans-=(ans/b)*b;
}
while(res.n && !res.a[res.n]) res.n--;
return res;
}
inline int operator %(const ll &b){
ll res=0;
for(int i=n;i;i--){
res=(res<<1)+(res<<3)+a[i];
if(res>=b) res-=(res/b)*b;
}
return res;
}
inline void read(){
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) a[++n]=ch^48,ch=getchar();
reverse(a+1,a+n+1);
}
}l;
ll f[31],mod;
int main(){
int n=read(),m=read(),k=read(),q=read();
f[1]=1,f[2]=2,mod=3*n-3;
for(int i=3;i<=30;i++) f[i]=f[i-1]*3ll;
l.n=1;l.a[1]=1;
while(q--){
gj p;p.read();
ll res=p%mod;
p=p/mod,p=p+p,p=p+p;
if(res>0) p=p+l;
if(res>n-1) p=p+l;
if(res>n-1+k-1) p=p+l;
if(res>n-1+k-1+n-1) p=p+l;
for(int i=1;i<=29;i++) if(p%f[i+1]!=0) {cout<<i<<'\n';break;}
}
return 0;
}