Project Euler 155

Project Euler 155

题目

Counting Capacitor Circuits

An electric circuit uses exclusively identical capacitors of the same value \(C\).

The capacitors can be connected in series or in parallel to form sub-units, which can then be connected in series or in parallel with other capacitors or other sub-units to form larger sub-units, and so on up to a final circuit.

Using this simple procedure and up to n identical capacitors, we can make circuits having a range of different total capacitances. For example, using up to \(n=3\) capacitors of \(60\mu F\) each, we can obtain the following \(7\) distinct total capacitance values:

If we denote by \(D(n)\) the number of distinct total capacitance values we can obtain when using up to n equal-valued capacitors and the simple procedure described above, we have: \(D(1)=1, D(2)=3, D(3)=7 \dots\)

Find \(D(18)\).

Reminder : When connecting capacitors \(C_1, C_2\) etc in parallel, the total capacitance is \(C_T=C_1+C_2+\dots\), whereas when connecting them in series, the overall capacitance is given by:\(\dfrac{1}{C_T}=\dfrac{1}{C_1}+\dfrac{1}{C_2}+\dots\).

解决方案

目前的办法应该只有暴力枚举,剩下的只是优化:

  1. 为减少枚举量,如果全局集合已经有的值,那就不需要继续添加到当前集合了。
  2. 实现一个简易的分数类,避免用浮点数产生误差,同时避免进行除法操作。

枚举的思想:如果已经有一对整体的电容值分别是\(u,v\),那么分别把这两“块”进行串联或者并联,得到新值\(\dfrac{1}{\dfrac{1}{u}+\dfrac{1}{v}},u+v\)

这个数列在OEIS上的查询结果为A153588

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 18;
struct Fraction{
ll num,den;
Fraction operator + (Fraction f){
ll a = num*f.den+den*f.num;
ll b = den*f.den;
ll g=__gcd(a,b);
return {a/g,b/g};
}
Fraction inv(){
return {den,num};
}
//这里的小于只是为了用于区分分数的不同,而并非是分数的值大小本身。
bool operator < (const Fraction &f) const{
return num<f.num||num==f.num&&den<f.den;
}
};
set<Fraction>st,now[N+2];
int main(){
st.insert(Fraction{1,1});
now[1].insert(Fraction{1,1});
for(int i=2;i<=N;i++){
for(int j=1;j<=i/2;j++){
for(Fraction u:now[j]){
for(Fraction v:now[i-j]){
Fraction x=u+v,y=(u.inv()+v.inv()).inv();
if(!st.count(x)){
st.insert(x);
now[i].insert(x);
}
if(!st.count(y)){
st.insert(y);
now[i].insert(y);
}
}
}
}
}
int ans=st.size();
printf("%d\n",ans);

}