Cod sursa(job #3139201)

Utilizator Ilie_MityIlie Dumitru Ilie_Mity Data 26 iunie 2023 14:03:20
Problema Frac Scor 30
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 1.37 kb
//Ilie Dumitru
#include<cstdio>

long long int divPrm[50], cntD;
long long int prodMask[1<<15], parit[1<<15];

long long int phi(long long int N)
{
	long long int ans=N;
	long long int i;

	if(N%2==0)
	{
		while(N%2==0)
			N>>=1;
		ans>>=1;
		divPrm[0]=2;
		cntD=1;
	}

	for(i=3;i*i<=N;i+=2)
	{
		if(N%i==0)
		{
			while(N%i==0)
				N/=i;
			ans-=ans/i;
		}
		divPrm[cntD++]=i;
	}

	if(N>1)
	{
		ans-=ans/N;
		divPrm[cntD++]=N;
	}

	return ans;
}

void genMasks()
{
	int i, mask, par;
	long long int p;

	for(mask=1;mask<(1<<cntD);++mask)
	{
		for(p=1, i=par=0;i<cntD;++i)
			if(mask&(1<<i))
			{
				p*=divPrm[i];
				par^=1;
			}
		prodMask[mask]=p;
		parit[mask]=par;
	}
}

long long int cntCoPrime(long long int K)
{
	int mask;
	long long int ans=K;

	for(mask=1;mask<(1<<cntD);++mask)
	{
		if(parit[mask])
			ans-=K/prodMask[mask];
		else
			ans+=K/prodMask[mask];
	}

	return ans;
}

int main()
{
	FILE* f=fopen("frac.in", "r"), *g=fopen("frac.out", "w");
	//FILE* f=stdin, *g=stdout;
	long long int N, P, fi, base, l, r, mid;

	fscanf(f, "%lld%lld", &N, &P);
	fi=phi(N);
	genMasks();
	base=(P-1)/fi*N;
	P=(P-1)%fi+1;

	l=0;
	r=N;
	while(r-l>1)
	{
		mid=l+((r-l)>>1);
		if(cntCoPrime(mid)<P)
			l=mid;
		else
			r=mid;
	}

	fprintf(g, "%lld\n", base+r);

	fclose(f);
	fclose(g);
	return 0;
}