E. Resistors in Parallel
[link](Problem - E - Codeforces)
题意
给你n个电阻,如果第i个电阻可以被一个大于1的完全平方数整除,他的阻值就是无穷,否则就是i。现在给你n个选择,每一个选择包含一个电阻集合,该集合由所有i的因数j,第j个电阻构成。让你选择其中一个集合,要求这些电阻并起来最小。
题解
我们要并联后的尽可能小,所以要分母尽可能大。第i个操作的集合所包含的电阻都是i的约数,任意一个数都可以被拆成一些质数的乘积,因为所有有平方因子的都是INF,所以对于重复的质因子是没有贡献的,只是和不同质因子有关。对于每一个质因子选于不选,构成的约数集合。化简以后分子就是前n个素数的乘积,分母是所有的约数相加,也就相当于一个二项式,也就是前n个素数,每一个素数加1然后相乘。
因此其实某一个数的素因子的个数并不重要,于是我们开始找规律:
易得,分子1 2 6 30 210......
它们按照乘2, 乘3, 乘5, 乘7.....
通过打表可知分母按照1 3 12 72 576....
它们按照乘3, 乘4, 乘6, 乘8.....(比分子的乘积恰好+1)
于是我们便可以爆搜找满足区间的最大数。(BigInteger)
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
static int[] a = new int[1005];
static int N = 200010;
static long[] primes = new long[N];
static long cnt = 0;
static int[] st = new int[N];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
init();
int T = sc.nextInt();
for (int k = 1; k <= T; k ++ )
{
BigInteger n = sc.nextBigInteger();
BigInteger s1 = new BigInteger("1");
BigInteger s2 = new BigInteger("1");
int idx = 0;
while (true)
{
if (s1.multiply(new BigInteger(String.valueOf(primes[idx]))).compareTo(n) <= 0)
{
s1 = s1.multiply(new BigInteger(String.valueOf(primes[idx])));
s2 = s2.multiply(new BigInteger(String.valueOf(primes[idx] + 1)));
}
else break;
idx ++ ;
}
BigInteger d = gcd(s1, s2);
s1 = s1.divide(d);
s2 = s2.divide(d);
System.out.println(s1 + "/" + s2);
}
}
static BigInteger gcd(BigInteger a, BigInteger b)
{
if (b.compareTo(new BigInteger("0")) == 0) return a;
else return gcd(b, a.mod(b));
}
static void init()
{
primes[0] = 0;
st[1] = st[0] = 1;
for (long i = 2; i < N; i ++ )
{
if (st[(int)i] == 0) primes[(int)cnt ++ ] = i;
for (long j = 0; primes[(int)j] * i < N; j ++ ) {
st[(int)(primes[(int)j] * i)] = 1;
if (i % primes[(int)j] == 0) break;
}
}
}
}