E. Resistors in Parallel
[link](Problem - E - Codeforces)
题意
给你n个电阻,如果第i个电阻可以被一个大于1的完全平方数整除,他的阻值就是无穷,否则就是i。现在给你n个选择,每一个选择包含一个电阻集合,该集合由所有i的因数j,第j个电阻构成。让你选择其中一个集合,要求这些电阻并起来最小。
题解
并联的公式是 R = 1 1 R 1 + 1 R 2 + . . . + 1 R k R=\frac {1}{\frac 1{R_1} + \frac 1{R_2}+...+ \frac 1{R_k}} R=R11+R21+...+Rk11,我们要并联后的尽可能小,所以要分母尽可能大。第i个操作的集合所包含的电阻都是i的约数,任意一个数都可以被拆成一些质数的乘积,因为所有有平方因子的都是INF,所以对于重复的质因子是没有贡献的,只是和不同质因子有关。对于每一个质因子选于不选,构成的约数集合。化简以后分子就是前n个素数的乘积,分母是所有的约数相加,也就相当于一个二项式,也就是前n个素数,每一个素数加1然后相乘。
由于数据范围太大,所以用java的大数类更为方便。
Code
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
static int []a = new int[1005];
static int N = 200005;
static long []primes = new long[N];
static long cnt = 0;
static int []ok = new int[N];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
primes[0] = 0;
ok[0] = 1;
ok[1] = 1;
get_prime();
int T = in.nextInt();
while ((int) T -- > 0) {
BigInteger n = in.nextBigInteger();
BigInteger sum1 = new BigInteger("1");
BigInteger sum2 = new BigInteger("1");
int i = 0;
while (true) {
if (sum1.multiply(new BigInteger(String.valueOf(primes[i]))).compareTo(n) <= 0) {
sum1 = sum1.multiply(new BigInteger(String.valueOf(primes[i])));
sum2 = sum2.multiply(new BigInteger(String.valueOf(primes[i] + 1)));
}
else break;
i ++;
}
BigInteger d = Gcd(sum1, sum2);
sum1 = sum1.divide(d);
sum2 = sum2.divide(d);
System.out.println(sum1+"/"+sum2);
}
}
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 get_prime() {
for (long i = 2; i < N; i ++ ) {
if (ok[(int)i] == 0) primes[(int)cnt ++] = i;
for (long j = 0; primes[(int)j] < N / i; j ++ ) {
ok[(int)(primes[(int)j] * i)] = 1;
if ((i % primes[(int)(j)]) == 0) break;
}
}
}
}