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;
}

posted @ 2021-07-05 09:23  WWW~~~  阅读(49)  评论(0编辑  收藏  举报