2018-2019 ACM-ICPC, Asia Jiaozuo Regional Contest-E. Resistors in Parallel

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;
            }
        }



    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值