Pagini recente » Cod sursa (job #847718) | preONI 2005 runda #1 - solutii | Cod sursa (job #2432546) | Cod sursa (job #1878313) | Cod sursa (job #610914)
Cod sursa(job #610914)
#include <assert.h>
#include <stdio.h>
enum { maxfactor = 14, maxfactorcomb = 1 << maxfactor };
long long n, wanted;
long long bottom, top, mid;
long long prime[maxfactor], primes;
long long factor[maxfactorcomb], factors;
int k, count_used;
long long product;
void check(long long p)
{
if(n % p == 0) prime[primes++] = p;
while(n % p == 0)
n /= p;
}
void calc_primes()
{
check(2);
for(long long p = 3; p * p < n; p += 2)
check(p);
if(n != 1) check(n);
assert(primes != 0);
}
void bkt()
{
if(k == primes)
{
if(count_used != 0) //screw 1
{
if(count_used % 2 == 1) factor[factors] = -product;
else factor[factors] = product;
factors++;
}
return;
}
assert(k >= 0 && k < primes);
//don't use
k++;
bkt();
k--;
//use
count_used++;
product *= prime[k];
k++;
bkt();
k--;
assert(product % prime[k] == 0);
product /= prime[k];
count_used--;
}
void calc_factors()
{
product = 1;
bkt();
}
long long attempt()
{
long long work = mid;
for(int i = 0; i < factors; i++)
{
work += mid / factor[i];
if(factor[i] < 0) work++;
else work--;
}
return work - 1;
}
void bsearch()
{
long long ans;
int i;
bottom = 1;
top = 1ll << 61; //better bounds?
while(true)
{
assert(bottom < top);
mid = (bottom + top) / 2;
//now fix it
while(mid >= bottom)
{
for(i = 0; i < primes; i++)
if(mid % prime[i] == 0) break;
if(i == primes) //relatively prime, as needed
break;
mid--;
}
if(mid == bottom - 1)
{
mid = (bottom + top) / 2 + 1;
while(mid <= top)
{
for(i = 0; i < primes; i++)
if(mid % prime[i] == 0) break;
if(i == primes) //passed
break;
mid++;
}
assert(mid <= top);
}
ans = attempt();
if(ans < wanted) //go higher
bottom = mid + 1;
else if(ans > wanted) //go lower
top = mid;
else //just right
break;
}
}
int main()
{
FILE *f = fopen("frac.in", "r");
if(!f) return 1;
fscanf(f, "%lld%lld", &n, &wanted);
fclose(f);
f = fopen("frac.out", "w");
if(!f) return 1;
calc_primes();
calc_factors();
bsearch();
fprintf(f, "%lld\n", mid);
fclose(f);
return 0;
}