这道题当时做的时候推不出来,晚上去找题解,不是Java,就是Python,对于只会c/c++的萌新,哎,难受。硬着头皮看了好久,大概懂了思路,第二天自己把前天的又推了一遍发现是自己计算错误的问题,要被自己蠢死,啊~~~
题意:n个电阻并联,第i个电阻值为i,但当下标i为d*d时(d>=2),电阻为无穷,即为0;能组成n个集合,求最小集合的总电阻值;
分类:找规律+大数
思路:根据答案去推每一个电阻值,当你推到第5个,即2310时,也许你就会发现什么(一定要自己推一遍,很有成就感);
1 1/1
2 2/3
6 1/2
30 5/12
210 35/96
2310 385/1152.....
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 40000;//筛4w的素数是远远够的
bool used[MAXN];
int prim[MAXN];//存放素数
int SIZE = 0;//素数的个数
void is_prim()//埃氏素筛法
{
for(int i = 2; i * i < MAXN; ++i)
{
if(!used[i])
for(int j = 2 * i; j < MAXN; j += i)
used[j] = true;
}
for(int i = 2; i < MAXN; ++i)
{
if(!used[i]) prim[++SIZE] = i;
if(SIZE>60) break;
}
}
string mul(string a,int b)
{
string c;
char s;
int len=a.length(),ok=0;
for(int i=len-1; i>=0; i--)
{
int temp=(a[i]-'0')*b+ok;
ok=temp/10;
s=temp%10+'0';
c=s+c;
}
while(ok)
{
s=ok%10+'0';
c=s+c;
ok/=10;
}
return c;
}
string div(string a,int b)
{
string c;
int len=a.length(),ans=0;
char s;
for(int i=0; i<len; i++)
{
ans=ans*10+a[i]-'0';
s=ans/b+'0';
ans%=b;
c+=s;
}
int pos=0;
while(pos<len && c[pos]=='0')
pos++;
if(pos==len)
return "0";
return c.substr(pos);
}
int MOD(string str,int mod)
{
int rem=0;
for(int i=0; i<str.length(); i++)
{
rem=rem*10+str[i]-'0';
rem=rem%mod;
}
return rem;
}
int main()
{
//预处理
string up[100],down[100];
is_prim();
for(int i=0; i<=70; i++)
{
up[i]="1";
down[i]="1";
}
for(int i=1; i<=60; i++)
{
up[i]=mul(up[i-1],prim[i]);
down[i]=mul(down[i-1],prim[i]+1);
}
int t;
cin>>t;
while(t--)
{
string n;
cin>>n;
if(n=="1")
cout<<"1/1"<<endl;
else
{
int pos=-1;
for(int i=1; i<=60; i++)
{
if(n.size()==up[i].size())
{
if(n<up[i]) {pos=i-1;break;}
}
else if(n.size()<up[i].size())
{
pos=i-1;break;
}
}
string ansu=up[pos],ansd=down[pos];
for(int i=1; i<=60; i++)
{
if((!MOD(ansu,prim[i]))&&(!MOD(ansd,prim[i])))
{
ansu=div(ansu,prim[i]);
ansd=div(ansd,prim[i]);
}
}
cout<<ansu<<"/"<<ansd<<endl;
}
}
return 0;
}
你会发现这是每次乘 (质数)/(当前质数+1)!!