题目大意
给出电阻的并联公式,规定一个含有平方因子的数的 1 R = 0 \frac{1}{R}=0 R1=0。定义一个数的阻值为其所有的因子阻值并联求出的结果,问 n n n以内并联后的最大的阻值是多少,输出分数形式
解题思路
打表不难知道在很大一段范围内答案是不变的,这体现在前几个数为 1 , 2 , 6 , 30 , 210 , 2310... 1,2,6,30,210,2310... 1,2,6,30,210,2310...,不难发现恰好是 1 , 1 ∗ 2 , 1 ∗ 2 ∗ 3 , 1 ∗ 2 ∗ 3 ∗ 5 , 1 ∗ 2 ∗ 3 ∗ 5 ∗ 7 , 1 ∗ 2 ∗ 3 ∗ 5 ∗ 7 ∗ 11... 1,1*2,1*2*3,1*2*3*5,1*2*3*5*7,1*2*3*5*7*11... 1,1∗2,1∗2∗3,1∗2∗3∗5,1∗2∗3∗5∗7,1∗2∗3∗5∗7∗11...
但是这个时候如何去找规律呢,我曾尝试质因数分解,然后递推去求,但是这样最后的因子个数会达到 2 100 2^{100} 2100个,明显爆了。后来也想不出什么,去搜了题解,结果竟然是找了积性函数的规律。
设 f ( x ) f(x) f(x)为 x x x的因子并联的阻值,显然 f ( p ) = 1 1 + 1 p = p p + 1 f(p)=\frac{1}{1+\frac{1}{p}}=\frac{p}{p+1} f(p)=1+p11=p+1p,而 f ( p 1 p 2 ) = 1 1 + 1 p 1 + 1 p 1 p 2 + 1 p 2 = p 1 p 2 p 1 + 2 p 1 p 2 + p 2 = f ( p 1 ) f ( p 2 ) f(p_1p_2)=\frac{1}{1+\frac{1}{p_1}+\frac{1}{p_1p_2}+\frac{1}{p_2}}=\frac{p_1p_2}{p_1+2p_1p_2+p_2}=f(p_1)f(p_2) f(p1p2)=1+p11+p1p21+p211=p1+2p1p2+p2p1p2=f(p1)f(p2)
使用Java大数,那么这样就能愉快的预处理了!
import java.math.BigInteger;
import java.util.*;
public class Main {
static long prime[] = new long[1005];
static boolean vis[] = new boolean[1005];
static BigInteger fz[] = new BigInteger[1005], fm[] = new BigInteger[1005];
static BigInteger array[] = new BigInteger[1005];
static int cnt, T, tot;
static void getPrime() {
for (int i = 0; i < 1005; i++) vis[i] = false;
vis[1] = false;
cnt = 0;
for (int i = 2; i < 1005; i++) {
if (!vis[i]) {
prime[++cnt] = i;
}
for (int j = 1; j <= cnt && i * prime[j] < 1005; j++) {
vis[(int) (i * prime[j])] = true;
if (i % prime[j] == 0) break;
}
}
}
static void init() {
BigInteger Max = BigInteger.ONE;
for (int i = 1; i <= 100; i++) {
Max = Max.multiply(BigInteger.TEN);
}
BigInteger res = BigInteger.ONE;
fz[0] = BigInteger.ONE;
fm[0] = BigInteger.ONE;
array[0] = BigInteger.ZERO;
for (int i = 1; i <= cnt; i++) {
res = res.multiply(BigInteger.valueOf(prime[i]));
//System.out.println(res);
array[i] = res;
if (res.compareTo(Max) > 0) {
break;
}
fm[i] = fm[i - 1].multiply(BigInteger.valueOf(prime[i]).add(BigInteger.ONE));
fz[i] = fz[i - 1].multiply(BigInteger.valueOf(prime[i]));
//System.out.println(fz[i] + "/" + fm[i]);
BigInteger gcd = fz[i].gcd(fm[i]);
fz[i] = fz[i].divide(gcd);
fm[i] = fm[i].divide(gcd);
}
}
public static void main(String[] args) {
getPrime();
init();
BigInteger n;
Scanner scanner = new Scanner(System.in);
T = scanner.nextInt();
while ((T--) != 0) {
n = scanner.nextBigInteger();
if (n.compareTo(BigInteger.ONE) == 0) {
System.out.println("1/1");
continue;
}
int idx = 0;
for (int i = 1; ; i++) {
if (n.compareTo(array[i]) == 0) {
idx = i;
break;
}
if (n.compareTo(array[i - 1]) > 0 && n.compareTo(array[i]) < 0) {
idx = i - 1;
break;
}
}
if (fz[idx] == fm[idx]) {
System.out.println("1/1");
} else System.out.println(fz[idx] + "/" + fm[idx]);
}
}
}