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

題目鏈接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 kk resistors with resistances R1,R2,...,RkR_1, R_2, ..., R_k in parallel and their combined resistance RR:
R=11R1+1R2++1Rk. R=\frac{1}{\frac{1}{R_1}+\frac{1}{R_2}+\cdots+\frac{1}{R_k}}.
Now you have nn resistors, the ii-th of which has a resistance of rir_i ohms with the equation
ri={if i can be divided by d2  for some integers d2iotherwise.  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.
You also have nn selections, the ii-th of which is a set of resistors SiS_i such that
Si={ 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\}.
Please find a selection in which the resistors form a parallel resistor with the minimum resistance and output the reduced fraction pq\frac{p}{q} of its resistance.

Input

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

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

Output

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

Example

Input

3
10
100
1000

Output

1/2
5/12
35/96

Problem solving report:

Description:如果ii是完全平方數(4)(\geqslant 4)的倍數,那麼ii號電阻的阻值爲無窮大,否則爲ii
現在有編號爲1n1\sim n的集合,每個集合包含若干個電阻,編號爲ii的集合包含所有編號爲ii的約數的電阻。求一個集合,使該集合內所有電阻的並聯阻值最小。
Problem solving

  • 首先,對於一個電阻,如果它能改變總電阻,那麼它的阻值不是無窮大,因此它的每個質因子最多被乘了一次。所以對於每個電阻的集合,它的編號的約數中,只有11、質因數、以及若干個不同質因數的積是有效的。另外,如果一個數的約數包含了若干個質因數,那麼這個數的約數也必然包含這些質因數的積
  • 並聯越多小電阻,總電阻越小,那就從最小的電阻開始選,越多越好,並且每個質因子只考慮一次。能選第ii個素數時,nn應該不小於前ii個素數的乘積,這樣才能保證前ii個素數在前ii個集合中同時出現在某一個集合內。
  • 選出包含前ii個素數的集合之後,該集合內的電阻應包括該ii個素數和該ii個素數所有組合出的乘積。設已經求出的電阻倒數之和爲sumsum,下一個素數爲pp。則加入下一個電阻時有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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章