CodeForces - [ACM-ICPC Jiaozuo Onsite D]Resistors in Parallel(高精度C++)

522 篇文章 3 订阅
18 篇文章 0 订阅

题目链接https://codeforces.com/gym/102028/problem/E
Time limit: 2.0 s Memory limit: 1024 MB

Problem Description

In this physics problem, what we are concerned about are only resistors. If you are poor at physics, do not worry, since solving this problem does not require you to have advanced abilities in physics.

Resistors are said to be connected together in parallel when both of their terminals are respectively connected to each terminal of the other resistors.
在这里插入图片描述

We have the following parallel resistor equation for k k k resistors with resistances R 1 ,   R 2 ,   . . . ,   R k R_1, R_2, ..., R_k R1,R2,...,Rk in parallel and their combined resistance R R R:
R = 1 1 R 1 + 1 R 2 + ⋯ + 1 R k . R=\frac{1}{\frac{1}{R_1}+\frac{1}{R_2}+\cdots+\frac{1}{R_k}}. R=R11+R21++Rk11.
Now you have n n n resistors, the i i i-th of which has a resistance of r i r_i ri ohms with the equation
r i = { ∞ if  i  can be divided by  d 2    for some integers  d ≥ 2 i otherwise.  r_{i}=\left\{\begin{array}{ll}{\infty} & {\text {if } i \text { can be divided by } d^{2} \text {\; for some integers } d \geq 2} \\ {i} & {\text {otherwise. }}\end{array}\right. ri={iif i can be divided by d2for some integers d2otherwise. 
You also have n n n selections, the i i i-th of which is a set of resistors S i S_i Si such that
S i = {  the  j  -th resistor  ∣   j  is a divisor of  i } . S_{i}=\{\text { the } j \text { -th resistor } |\ j \text { is a divisor of } i\}. Si={ the j -th resistor  j is a divisor of i}.
Please find a selection in which the resistors form a parallel resistor with the minimum resistance and output the reduced fraction p q \frac{p}{q} qp of its resistance.

Input

The input contains several test cases, and the first line contains a positive integer T T T indicating the number of test cases which is up to 100 100 100.

For each test case, the only one line contains an integer n n n, where 1   ≤   n   ≤   1 0 100 1 ≤ n ≤ 10^{100} 1n10100.

Output

For each test case, output a line containing a reduced fraction of the form p / q p/q p/q indicating the minimum possible resistance, where p p p and q q q should be positive numbers that are coprime.

Example

Input

3
10
100
1000

Output

1/2
5/12
35/96

Problem solving report:

Description:如果 i i i是完全平方数 ( ⩾ 4 ) (\geqslant 4) (4)的倍数,那么 i i i号电阻的阻值为无穷大,否则为 i i i
现在有编号为 1 ∼ n 1\sim n 1n的集合,每个集合包含若干个电阻,编号为 i i i的集合包含所有编号为 i i i的约数的电阻。求一个集合,使该集合内所有电阻的并联阻值最小。
Problem solving

  • 首先,对于一个电阻,如果它能改变总电阻,那么它的阻值不是无穷大,因此它的每个质因子最多被乘了一次。所以对于每个电阻的集合,它的编号的约数中,只有 1 1 1、质因数、以及若干个不同质因数的积是有效的。另外,如果一个数的约数包含了若干个质因数,那么这个数的约数也必然包含这些质因数的积
  • 并联越多小电阻,总电阻越小,那就从最小的电阻开始选,越多越好,并且每个质因子只考虑一次。能选第 i i i个素数时, n n n应该不小于前 i i i个素数的乘积,这样才能保证前 i i i个素数在前 i i i个集合中同时出现在某一个集合内。
  • 选出包含前 i i i个素数的集合之后,该集合内的电阻应包括该 i i i个素数和该 i i i个素数所有组合出的乘积。设已经求出的电阻倒数之和为 s u m sum sum,下一个素数为 p p p。则加入下一个电阻时有 s u m = s u m ∗ ( 1 + 1 / p ) sum = sum*(1+1/p) sum=sum(1+1/p),这样就可以很顺利的求出最终结果的倒数。因为要输出成分数形式,所以在递推的过程要分别保存分子和分母,最后输出前记得约分。

Accepted Code:

/* 
 * @Author: lzyws739307453 
 * @Language: C++ 
 */
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 5;
bool isp[MAXN];
char str[MAXN];
int pre[MAXN], cnt;
struct edge {
    int p[MAXN], size;
    edge() {//初始化
        size = 0;
        memset(p, 0, sizeof(p));
    }
    int cmp(edge b) {//高精度比大小
        if (size > b.size) return 1;
        if (size < b.size) return -1;
        for (int i = size - 1; ~i; i--) {
            if (p[i] > b.p[i]) return 1;
            if (p[i] < b.p[i]) return -1;
        }
        return 0;
    }
    edge mul(int b) {//高精度*单精度
        edge c;
        int t = 0;
        for (int i = 0; i < size || t; i++) {
            if (i < size)
                t += p[i] * b;
            c.p[c.size++] = t % 10;
            t /= 10;
        }
        return c;
    }
    edge Mul(edge b) {//高精度*高精度
        edge c;
        int t = 0;
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < b.size; j++) {
                t += p[i] * b.p[j];
                c.p[i + j] += t % 10;
                t /= 10;
            }
        }
        c.size = size + b.size - 1;
        while (t) {
            c.p[c.size++] = t % 10;
            t /= 10;
        }
        return c;
    }
    edge Sub(edge b) {//高精度-高精度
        edge c;
        int t = 0;
        for (int i = 0; i < size; i++) {
            t = p[i] - t;
            if (i < b.size)
                t -= b.p[i];
            c.p[i] = (t + 10) % 10;
            t = t < 0;
        }
        c.size = size;
        while (c.size > 1 && !c.p[c.size - 1]) --c.size;
        return c;
    }
    edge Div(edge b) {//高精度/高精度
        edge quo, rem = *this;
        quo.size = 1, quo.p[0] = 0;
        if (rem.cmp(b) < 0)
            return quo;
        quo.size = rem.size - b.size;
        for (int i = rem.size - 1; ~i; i--) {
            if (i >= quo.size) b.p[i] = b.p[i - quo.size];
            else b.p[i] = 0;
        }
        b.size = rem.size;
        for (int i = 0; i <= quo.size; i++) {
            while (rem.cmp(b) >= 0) {
                rem = rem.Sub(b);
                quo.p[quo.size - i]++;
            }
            for (int j = 0; j < b.size - 1; j++)
                b.p[j] = b.p[j + 1];
            --b.size;
        }
        ++quo.size;
        while (quo.size > 1 && !quo.p[quo.size - 1]) --quo.size;
        return quo;
    }
    edge Mod(edge b) {//高精度%高精度
        edge quo, rem = *this;
        quo.size = 1, quo.p[0] = 0;
        if (rem.cmp(b) < 0)
            return rem;
        quo.size = rem.size - b.size;
        for (int i = rem.size - 1; ~i; i--) {
            if (i >= quo.size) b.p[i] = b.p[i - quo.size];
            else b.p[i] = 0;
        }
        ++quo.size;
        b.size = rem.size;
        for (int i = 0; i < quo.size; i++) {
            while (rem.cmp(b) >= 0) {
                rem = rem.Sub(b);
                quo.p[quo.size - i - 1]++;
            }
            for (int j = 0; j < b.size - 1; j++)
                b.p[j] = b.p[j + 1];
            --b.size;
        }
        while (rem.size > 1 && !rem.p[rem.size - 1]) --rem.size;
        return rem;
    }
	edge gcd(edge b) {//高精度取最大公约数
		if (!b.p[0] && b.size == 1)
			return *this;
		return b.gcd(Mod(b));
	}
};
void Get_prime(int n) {//质数筛
    cnt = 0;
    for (int i = 2; i < n; i++) {
        if (!isp[i])
            pre[cnt++] = i;
        for (int j = 0; i * pre[j] < n && j < cnt; j++) {
            isp[i * pre[j]] = true;
            if (!(i % pre[j]))
                break;
        }
    }
}
int main() {
    int t;
    Get_prime(300);
    scanf("%d", &t);
    while (t--) {
        edge m, Mol, Den;
        scanf("%s", str);
        int len = strlen(str);
        for (int i = 0; i < len; i++)
            m.p[len - i - 1] = str[i] - '0';
        m.size = len;
        Mol.size = 1, Mol.p[0] = 1;
        Den.size = 1, Den.p[0] = 1;
        for (int i = 0; Mol.mul(pre[i]).cmp(m) <= 0; i++) {
            Mol = Mol.mul(pre[i]);
            Den = Den.mul(pre[i] + 1);
        }
        edge Gcd = Den.gcd(Mol);
        Mol = Mol.Div(Gcd), Den = Den.Div(Gcd);
        for (int i = Mol.size - 1; ~i; i--)
            printf("%d", Mol.p[i]);
        printf("/");
        for (int i = Den.size - 1; ~i; i--)
            printf("%d", Den.p[i]);
        printf("\n");
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ityanger

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值