题意:
定义n种电阻,阻值 { inf | i%d2==0 && d>1 , i | else} 。
然后定义n种电阻集合,S[i]={ j | i%j==0} , 现在询问给定n找出一个集合Si,使得将Si内的电阻
并联之后电阻值最小,输出最简分数格式。
思路:
确定题意弄了半天,不是依次选择N个电阻,而是有N种选择集合,每种选择中固定有
若干电阻。想不出什么规律打了个表(直接分数转成小数打表打错了,但是只注意到前面
打对的几项,巧合了,,,)。发现 N==x 时 的答案是符合一定规律的,N<=1时取n=1,
1<N<=2时取i=2得最优解,2<N<=6时取 i==6,N<6<=30时 取 i==30,,,呈质数倍数
关系增长。(打分数表的直接把分子分母的规律给打出来了,但我们没打出来,所以打表的
技巧有待加强)。
在只有上述结论的情况下,大佬秀基本操作的时候到了。。。
1、现在已知N,我们要找的是规律序列中第一个大于等于N的数?
暴力考虑质数相乘 递推过去 即可,N最大10^100,几百个质数相乘就够了,
打个素数表递推,
时间上没问题,精度上可以用Java处理。
2、现在已知 我们从种方案中选择了 第 种方案,怎么计算该方案 的并联阻值?
因为所有参与并联电路的阻值都肯定不包含完全平方数,所以不考虑电阻无穷情况,
(其实包含也不影响,,,),同时,这些电阻值均为 的因子,所以对电阻并联公式
通分最后分子等于 ,分母为 的因子和。分子好说,分母的话时间上存在问题。
这里用积性函数优化,设S(N)表示N的因子和,显然N=x*y*...*z。x,y为累乘的质数
们,互质显然的,所以分母变为(x+1)*(y+1)*...*(z+1)。时间解决了,空间大数
即可。
代码实现:
import java.math.BigInteger;
import java.util.Scanner;
public class Main{
static int t, tot;
static BigInteger n;
static int vis[] = new int[1000100];
static int pri[] = new int[1000100];
static Scanner cin = new Scanner(System.in);
static void init(int maxsn){
vis[1]=vis[0]=1;
for(int i=2;i<=maxsn;i++){
if(vis[i]==1)continue;
pri[++tot]=i;
for(int j=i;j*i<=maxsn;j++)
vis[i*j]=1;
}
}
static String sol_gcd(BigInteger x,BigInteger y){
BigInteger zero = new BigInteger("0");
return y.equals(zero)?x.toString():sol_gcd(y,x.mod(y));
}
static void sol(){
BigInteger fz=new BigInteger("1");
BigInteger fm=new BigInteger("1");
BigInteger p=null;
for(int i=1;i<=tot;i++){
p = BigInteger.valueOf(pri[i]);//*** ***
if((fz.multiply(p).compareTo(n))==1)break;
fz = fz.multiply(p);
fm = fm.multiply(p.add(new BigInteger("1")));
}
BigInteger d = new BigInteger(sol_gcd(fz,fm));
fz = fz.divide(d);
fm = fm.divide(d);
System.out.println(fz+"/"+fm);
}
public static void main(String args[]){
t = cin.nextInt();
tot = 0;
init(10000);
while (t > 0) {
t--;
n=new BigInteger(cin.next());
sol();
}
cin.close();
}
}
THE END;