837EVasya's Function 数论

来源:互联网 发布:苏州爱知科技怎么样 编辑:程序博客网 时间:2024/06/05 09:13

题目链接


题意:


定义F(a,0) = 0,F(a,b) = 1 + F(a,b - GCD(a,b)。给定 x 和 y (<=1e12)求F(x,y)。


思路:

这个题乍一看我们好像都会做点,但是一直TLE啊.

     难点在于如何快速的找到 b减掉了多少次gcd,使得新的a 和 b gcd 发生了改变,那么我们设 a = A*gcd(a,b) ,

b = B*gcd(a,b). 设最少进行了S次后 gcd变为 T*gcd,那么有 (B-S)%T= 0(其中T必是A中的因子);( B%T-S%T)%T=0 这里S一定小于T.

因为我们设 B = k*T+S.那么如果S不小于T的话,一定有 B=(K+1)*T+S'.那么S一定不是最小的,与上述假设矛盾.所以我们将(B-S)%T=0 变形为 S=min(B%T) (因为我们这里要找的S最小). 找到这个S之后,我们就知道这一次需要加几个1,然后得到了新的gcd,将a/gcd,b/gcd。再将剩下的问题继续迭代就好》

然后我们发现,如果每次都用O(N^(1/2))的复杂度来枚举A的因子来求S的话还是会T。我们通过观察上述式子,

S=min(B%T) (T为A的因子) 可以发现这个能达到最小值的T,一定是A的素因子.因为你如果非素因子整除A,那么这个A的素因子一定可以整除A,且使得余数更小.比如B为7 ,A为8,如果7%4=3 ,7%2=1 .就是举个例子..

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int mod=1e9+7;const int maxn=1e5+10;ll a,b;ll ans;vector<ll>prime; int main(){scanf("%lld %lld",&a,&b);ll tmp = a;for(ll i = 2;i * i <= tmp;i++)//i 没开ll T了一下午 {if(tmp % i  == 0){prime.push_back(i);while(tmp % i == 0)tmp /= i;}}if(tmp > 1)prime.push_back(tmp);ans = 0;int len = prime.size();while(b){ll g = __gcd(a,b);a /= g;b /= g;ll res = b;for(ll i = 0;i < len;i++){ll x = prime[i];if(a % x == 0)res = min (res,b % x);}ans += res;b -= res;}printf("%lld\n",ans);return 0;}


原创粉丝点击