AGC 015 F Kenus the Ancient Greek 题解
AGC 015 F Kenus the Ancient Greek 题解
首先能进行至少\(k\)次的数对最小是\((fib_k,fib_{k+1})\)。
所以第一问很好做。
但是满足条件的数对非常多,考虑将他们归到一些等价类。
不妨设\((x,y),(x<y\and y<2x)\)
则\((x,y),(x,y+x),(x,y+2x...)\)的步数都一样,称\((x,y)\)为最小表示的数对。
可以证明答案为\(k\)的等价类恰好\(k\)个。
这个可以地推得到。
所以地推出所有最小表示数对即可。
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
// int x=0;
// char ch=getchar();
// while(ch<'0'||ch>'9'){
// ch=getchar();
// }
// while(ch>='0'&&ch<='9'){
// x=(x<<1)+(x<<3)+(ch^48);
// ch=getchar();
// }
// return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXQ=3e5+233;
vector<LL> fib;
const int MOD=1e9+7;
vector<vector<pair<LL,LL> > > pa;
LL solve(LL x,LL y,int ans){
if(x<pa[ans][0].FIR||y<pa[ans][0].SEC) return 0;
LL __=0;
for(auto it:pa[ans]){
if(x>=it.FIR&&y>=it.SEC) __+=(y-it.SEC)/it.FIR+1,__%=MOD;
}
return __;
}
int main(){
fib.PB(1);
fib.PB(1);
while(fib.back()+fib[fib.size()-2]<=1e18){
fib.PB(fib.back()+fib[fib.size()-2]);
// cout<<fib.back()<<endl;
}
pa.resize(fib.size()-1);
pa[1]={II(1,2)};
rb(i,2,fib.size()-2){
for(auto it:pa[i-1]){
pa[i].PB(II(it.SEC,it.FIR+it.SEC));
}
pa[i].PB(II(pa[i-1][0].FIR+pa[i-1][0].SEC,pa[i-1][0].FIR+pa[i-1][0].SEC+pa[i-1][0].FIR));
}
// rb(i,1,pa.size()-1){
// cout<<i<<" ";
// for(auto it:pa[i]){
// cout<<"("<<it.FIR<<","<<it.SEC<<") ";
// }
// cout<<endl;
// }
int Q;
scanf("%d",&Q);
while(Q--){
LL x,y;
scanf("%lld%lld",&x,&y);
if(x>y) swap(x,y);
int ans=1;
rb(i,1,pa.size()-1) if(x>=pa[i][0].FIR&&y>=pa[i][0].SEC) ans=i;
if(ans==1){
printf("1 %lld\n",(x%MOD)*(y%MOD)%MOD);
continue;
}
// cout<<solve(x,y,ans)<<endl;
// cout<<solve(y,x,ans)<<endl;
LL __=solve(x,y,ans)+solve(y,x,ans);
printf("%d %lld\n",ans,__%MOD);
}
return 0;
}