# 【题解】Probe Droids - The North American Invitational Programming Contest 2018 F

## 【大意】

$$q$$ 次询问，每次询问数字 $$x$$ ，询问第 $$x$$ 个消灭的敌人的坐标。

## 【分析】

\begin{aligned} ans&=\sum_{i=1}^{m-1}\sum_{j=1}^{n-1}[j\leq {ia\over b}] \\\\&=\sum_{i=1}^{m-1}\min\{n-1, \lfloor{ia\over b}\rfloor\} \\\\&=\sum_{i=1}^{\min\{m-1,\lfloor {b(n-1)+b-1\over a}\rfloor\}}\lfloor{ia\over b}\rfloor+\sum_{i=\min\{m-1,\lfloor {b(n-1)+b-1\over a}\rfloor\}+1}^{m-1}(n-1) \\\\&=\sum_{i=1}^{\min\{m-1,\lfloor {bn-1\over a}\rfloor\}}\lfloor{ia\over b}\rfloor+(n-1)\cdot \max\{m-1-\min\{m-1,\lfloor {bn-1\over a}\rfloor\}, 0\} \\\\&=\sum_{i=1}^{lim} \lfloor{ia\over b}\rfloor+(n-1)\cdot \max\{m-1-lim,0\}&,lim:=\min\{m-1,\lfloor {bn-1\over a}\rfloor\} \end{aligned}

## 【代码】

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dd(x) cerr << #x <<" = "<< x <<" "
#define de(x) cerr << #x <<" = "<< x <<endl
int n, m, q;
inline ll likeEucilid(ll a,ll b,ll c,ll n){
ll f=0;
if(a>=c||b>=c){
ll ans=likeEucilid(a%c,b%c,c,n);
ll ac=a/c,bc=b/c,s0=(n+1),s1=n*(n+1)/2;
f=(ac*s1+bc*s0+ans);
}
else if(a!=0){
ll m=(a*n+b)/c;
ll ans=likeEucilid(c,c-b-1,a,m-1);
f=(n*m-ans);
}
return f;
}
inline ll calc(int a, int b) {//sum j=1->m sum i=1->n [i<=ja/b]
int lim=min((ll)m-1, ((ll)b*n-1)/a);
return likeEucilid(a, 0, b, lim)+(ll)(n-1)*max(m-1-lim, 0);
}
inline void query(int a, int b, int c, int d, ll pos, int &x, int &y) {
int nowa=a+c, nowb=b+d;
ll tot=calc(nowa, nowb);
if(pos>tot) return query(nowa, nowb, c, d, pos, x, y), void();
int cnt=min((n-1)/nowa, (m-1)/nowb);
if(pos>tot-cnt) return pos-=tot-cnt, x=pos*nowa, y=pos*nowb, void();
query(a, b, nowa, nowb, pos, x, y);
}
inline void work() {
ll pos;
int x, y;
cin>>pos;
if(pos>(ll)n*m-n)
x=pos-((ll)n*m-n), y=0;
else if(pos<=m-1)
x=0, y=pos;
else
query(0, 1, 1, 0, pos-(m-1), x, y);
cout<<x+1<<" "<<y+1<<"\n";
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m>>q;
while(q--) work();
cout.flush();
return 0;
}

posted @ 2022-01-05 23:44  JustinRochester  阅读(31)  评论(0编辑  收藏  举报