1. 程式人生 > >Educational Codeforces Round 26-E-Vasya's Function(思維)

Educational Codeforces Round 26-E-Vasya's Function(思維)


題意:見體面,就是求f(x,y)

題解:假如我們模擬遞推肯定炸,因為x和y有1e12這麼大,因此我們要看看這裡邊是否存在著無用功,首先因為每次b都會減掉一個gcd(a,b),我們可以將a和b分別寫成x1*gcd(a,b)和x2*gcd(a,b),當然這裡x1和x2一定是互質的(廢話,都提取最大公約數了),到這裡你可能恍然大悟,你也可能誤入錯誤的思想無法自拔,因為你一定會覺得肯定要減掉min(x1,x2)次呀,直接除掉不就好了?......  當然不是了,因為假如你減了m次,此時x1還是x1,而x2是x2-m,但是假如gcd(x1,x2-m)>1呢不就炸了,因為此時減的gcd不再是之前的gcd了,想到這裡,這道題就已經可以過了,對於剛才說的情況,我們可以通過暴力a的所有質因數,呢每次該gcd對答案的貢獻一定是min(x2,b/(x1的某個質因數));然後我們重複過程直到b==0停止即可。

#include<stdio.h>
#include<algorithm>
using namespace std;
#define ll long long
ll x,y;
ll gcd(ll a,ll b)
{
	if(a%b==0)
		return b;
	return gcd(b,a%b);
}
ll work(ll a,ll b)
{
	if(b==0) return 0;
	ll g=gcd(a,b);a=a/g;b=b/g;
	ll aa=a,bb=b; ll mn=b;
	for(ll i=2;i*i<=a;i++)
	{
		if(a%i) continue;
		mn=min(mn,b%i);
		while(a%i==0) a/=i;
	}
	if(a!=1) mn=min(mn,b%a);
	return work(aa,bb-mn)+mn;
}
int main(void)
{
	scanf("%lld%lld",&x,&y);
	printf("%lld\n",work(x,y));
	return 0;
}