題目鏈接: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 resistors with resistances in parallel and their combined resistance :
Now you have resistors, the -th of which has a resistance of ohms with the equation
You also have selections, the -th of which is a set of resistors such that
Please find a selection in which the resistors form a parallel resistor with the minimum resistance and output the reduced fraction of its resistance.
Input
The input contains several test cases, and the first line contains a positive integer indicating the number of test cases which is up to .
For each test case, the only one line contains an integer , where .
Output
For each test case, output a line containing a reduced fraction of the form indicating the minimum possible resistance, where and should be positive numbers that are coprime.
Example
Input
3
10
100
1000
Output
1/2
5/12
35/96
Problem solving report:
Description:如果是完全平方數的倍數,那麼號電阻的阻值爲無窮大,否則爲。
現在有編號爲的集合,每個集合包含若干個電阻,編號爲的集合包含所有編號爲的約數的電阻。求一個集合,使該集合內所有電阻的並聯阻值最小。
Problem solving:
- 首先,對於一個電阻,如果它能改變總電阻,那麼它的阻值不是無窮大,因此它的每個質因子最多被乘了一次。所以對於每個電阻的集合,它的編號的約數中,只有、質因數、以及若干個不同質因數的積是有效的。另外,如果一個數的約數包含了若干個質因數,那麼這個數的約數也必然包含這些質因數的積。
- 並聯越多小電阻,總電阻越小,那就從最小的電阻開始選,越多越好,並且每個質因子只考慮一次。能選第個素數時,應該不小於前個素數的乘積,這樣才能保證前個素數在前個集合中同時出現在某一個集合內。
- 選出包含前個素數的集合之後,該集合內的電阻應包括該個素數和該個素數所有組合出的乘積。設已經求出的電阻倒數之和爲,下一個素數爲。則加入下一個電阻時有,這樣就可以很順利的求出最終結果的倒數。因爲要輸出成分數形式,所以在遞推的過程要分別保存分子和分母,最後輸出前記得約分。
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;
}