LCM Walk【2015上海現場賽】【推理】
阿新 • • 發佈:2018-12-16
題意:有已知的[ex, ey],求可以由[sx+lcm(sx, sy), sy]或者[sx, sy+lcm(sx, sy)]得到,求這樣的[sx, sy]的數目,當然,[ex, ey]也算是一組。
一道推理題,顯而易見,知[ex, ey]那我們得把關係聯絡起來,[sx+sx*sy/gcd, sy]=[ex, ey],則有sy=ey,又可知道gcd(sx, sy)==gcd(ex, ey)必定成立(可推導),所以我們能確定前一刻的sx,sx*(sy+gcd)=ex*gcd,sx=ex*gcd/(gcd+sy);於是,我們便把原來O(N)的複雜度下降了,我們只需要遍歷這樣的sx即可,並且,對於前一刻的[ex, ey]一定要有ex>ey才行,並且等式成立的條件還得是前後的gcd不得改變。
所以,列寫程式碼吧:
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef long long ll; ll N, M, ans, g; ll gcd(ll a, ll b) { return b==0?a:gcd(b, a%b); } ll solve(ll x, ll y) { ll up=x*g, down=y+g; if(down==0) return 0; if(up<down) return 0; if(up%down==0) return up/down; else return 0; } int main() { int T; scanf("%d", &T); for(int Cas=1; Cas<=T; Cas++) { scanf("%lld%lld", &N, &M); g=gcd(N, M); ans=0; ll a=N, b=M; while(gcd(a, b)==g) { if(a<b) swap(a, b); ll tmp=solve(a, b); if(tmp && gcd(tmp, b)==g) { ans++; a=tmp; } else break; } printf("Case #%d: %lld\n", Cas, ans+1); } return 0; }