2018焦作區域賽E. Resistors in Parallel
阿新 • • 發佈:2018-12-11
原題連結:http://codeforces.com/gym/102028/problem/E
解法:
打表找規律
可知分子1 2 6 30 210......
發現後一個等於前一個乘以2,3,5,7......
還可以發現分母1 3 12 72 576.。。。
發現後一個等於前一個乘以3,4,6,8......(也就是分子對應的質數加1)
那麼接下來就是大數問題了
Java程式碼如下:(真的簡短粗暴啊!)
1 //package 實驗; 2 import java.math.BigInteger; 3 import java.util.Scanner; 4 import java.util.*; 5 importjava.io.*; 6 import java.math.*; 7 public class Main { 8 static int[] p=new int[5050]; 9 static int[] p1=new int[5050]; 10 static int[] vis=new int[5050]; 11 static int cnt=0; 12 public static void init() { 13 for(int i=2;i<=5000;i++) { 14 if(vis[i]==1)continue;15 p[++cnt]=i; 16 p1[cnt]=i+1; 17 for(int j=i;j<=5000;j+=i) { 18 vis[j]=1; 19 } 20 } 21 } 22 public static void main(String [] args){ 23 init(); 24 int T; 25 Scanner sc=new Scanner(System.in); 26 T=sc.nextInt();27 while(true) { 28 BigInteger n=sc.nextBigInteger(); 29 BigInteger x=BigInteger.valueOf(1); 30 BigInteger x1=BigInteger.valueOf(1); 31 BigInteger y=BigInteger.valueOf(1); 32 BigInteger y1=BigInteger.valueOf(1); 33 BigInteger z=BigInteger.valueOf(1); 34 for(int i=1;i<=cnt;i++) { 35 //System.out.println(x); 36 y=x; 37 y1=x1; 38 x=x.multiply(BigInteger.valueOf(p[i])); 39 x1=x1.multiply(BigInteger.valueOf(p1[i])); 40 if(n.compareTo(x)==-1)break; 41 } 42 z=y.gcd(y1); 43 y=y.divide(z); 44 y1=y1.divide(z); 45 System.out.println(y+"/"+y1); 46 T--; 47 if(T<=0)break; 48 } 49 sc.close(); 50 } 51 }
C++程式碼:(這個有點迷,計算客可以過,cf交上去過不了,慎用)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int L=5010; 5 string add(string a,string b) 6 { 7 string ans; 8 int na[L]={0},nb[L]={0}; 9 int la=a.size(),lb=b.size(); 10 for(int i=0;i<la;i++) na[la-1-i]=a[i]-'0'; 11 for(int i=0;i<lb;i++) nb[lb-1-i]=b[i]-'0'; 12 int lmax=la>lb?la:lb; 13 for(int i=0;i<lmax;i++) na[i]+=nb[i],na[i+1]+=na[i]/10,na[i]%=10; 14 if(na[lmax]) lmax++; 15 for(int i=lmax-1;i>=0;i--) ans+=na[i]+'0'; 16 return ans; 17 } 18 string mul(string a,string b) 19 { 20 string s; 21 int na[L],nb[L],nc[L],La=a.size(),Lb=b.size();//na儲存被乘數,nb儲存乘數,nc儲存積 22 fill(na,na+L,0);fill(nb,nb+L,0);fill(nc,nc+L,0);//將na,nb,nc都置為0 23 for(int i=La-1;i>=0;i--) na[La-i]=a[i]-'0';//將字串表示的大整形數轉成i整形陣列表示的大整形數 24 for(int i=Lb-1;i>=0;i--) nb[Lb-i]=b[i]-'0'; 25 for(int i=1;i<=La;i++) 26 for(int j=1;j<=Lb;j++) 27 nc[i+j-1]+=na[i]*nb[j];//a的第i位乘以b的第j位為積的第i+j-1位(先不考慮進位) 28 for(int i=1;i<=La+Lb;i++) 29 nc[i+1]+=nc[i]/10,nc[i]%=10;//統一處理進位 30 if(nc[La+Lb]) s+=nc[La+Lb]+'0';//判斷第i+j位上的數字是不是0 31 for(int i=La+Lb-1;i>=1;i--) 32 s+=nc[i]+'0';//將整形陣列轉成字串 33 return s; 34 } 35 int sub(int *a,int *b,int La,int Lb) 36 { 37 if(La<Lb) return -1;//如果a小於b,則返回-1 38 if(La==Lb) 39 { 40 for(int i=La-1;i>=0;i--) 41 if(a[i]>b[i]) break; 42 else if(a[i]<b[i]) return -1;//如果a小於b,則返回-1 43 44 } 45 for(int i=0;i<La;i++)//高精度減法 46 { 47 a[i]-=b[i]; 48 if(a[i]<0) a[i]+=10,a[i+1]--; 49 } 50 for(int i=La-1;i>=0;i--) 51 if(a[i]) return i+1;//返回差的位數 52 return 0;//返回差的位數 53 54 } 55 string div(string n1,string n2,int nn)//n1,n2是字串表示的被除數,除數,nn是選擇返回商還是餘數 56 { 57 string s,v;//s存商,v存餘數 58 int a[L],b[L],r[L],La=n1.size(),Lb=n2.size(),i,tp=La;//a,b是整形陣列表示被除數,除數,tp儲存被除數的長度 59 fill(a,a+L,0);fill(b,b+L,0);fill(r,r+L,0);//陣列元素都置為0 60 for(i=La-1;i>=0;i--) a[La-1-i]=n1[i]-'0'; 61 for(i=Lb-1;i>=0;i--) b[Lb-1-i]=n2[i]-'0'; 62 if(La<Lb || (La==Lb && n1<n2)) { 63 //cout<<0<<endl; 64 return n1;}//如果a<b,則商為0,餘數為被除數 65 int t=La-Lb;//除被數和除數的位數之差 66 for(int i=La-1;i>=0;i--)//將除數擴大10^t倍 67 if(i>=t) b[i]=b[i-t]; 68 else b[i]=0; 69 Lb=La; 70 for(int j=0;j<=t;j++) 71 { 72 int temp; 73 while((temp=sub(a,b+j,La,Lb-j))>=0)//如果被除數比除數大繼續減 74 { 75 La=temp; 76 r[t-j]++; 77 } 78 } 79 for(i=0;i<L-10;i++) r[i+1]+=r[i]/10,r[i]%=10;//統一處理進位 80 while(!r[i]) i--;//將整形陣列表示的商轉化成字串表示的 81 while(i>=0) s+=r[i--]+'0'; 82 //cout<<s<<endl; 83 i=tp; 84 while(!a[i]) i--;//將整形陣列表示的餘數轉化成字串表示的</span> 85 while(i>=0) v+=a[i--]+'0'; 86 if(v.empty()) v="0"; 87 //cout<<v<<endl; 88 if(nn==1) return s; 89 if(nn==2) return v; 90 } 91 bool judge(string s)//判斷s是否為全0串 92 { 93 for(int i=0;i<s.size();i++) 94 if(s[i]!='0') return false; 95 return true; 96 } 97 string gcd(string a,string b)//求最大公約數 98 { 99 string t; 100 while(!judge(b))//如果餘數不為0,繼續除 101 { 102 t=a;//儲存被除數的值 103 a=b;//用除數替換被除數 104 b=div(t,b,2);//用餘數替換除數 105 } 106 return a; 107 } 108 int p[10005],vis[10005]; 109 char h[1000005]; 110 int cnt=0; 111 void init(){ 112 for(int i=2;i<=3000;i++){ 113 if(vis[i])continue; 114 p[++cnt]=i; 115 for(int j=i;j<=3000;j+=i){ 116 vis[j]=1; 117 } 118 } 119 } 120 void cal(int k){ 121 int c=0; 122 while(k>0){ 123 h[c++]=k%10+'0'; 124 k/=10; 125 } 126 h[c]='\0'; 127 for(int i=0;i<c/2;i++){ 128 swap(h[i],h[c-i-1]); 129 } 130 } 131 int ok(string x,string y){ 132 if(x.length()>y.length())return 1; 133 else if(x.length()<y.length())return 0; 134 int len=x.length(); 135 for(int i=0;i<len;i++){ 136 if(x[i]>y[i])return 1; 137 if(x[i]<y[i])return 0; 138 } 139 return 1; 140 } 141 string m[500],m1[500]; 142 void init1(){ 143 string x="1"; 144 for(int i=1;i<=100;i++){ 145 cal(p[i]); 146 string y=(string)h; 147 x=mul(x,y); 148 m[i]=x; 149 } 150 } 151 void init2(){ 152 string x="1"; 153 for(int i=1;i<=100;i++){ 154 cal(p[i]+1); 155 string y=(string)h; 156 x=mul(x,y); 157 m1[i]=x; 158 } 159 } 160 int T; 161 string s; 162 int main() 163 { 164 init(); 165 init1(); 166 init2(); 167 cin.sync_with_stdio(false); 168 cin>>T; 169 while(T--){ 170 cin>>s; 171 if(s=="1"){ 172 printf("1/1\n"); 173 continue; 174 } 175 int id=0; 176 for(int i=1;i<=100;i++){ 177 if(!ok(s,m[i])){ 178 id=i-1; 179 break; 180 } 181 } 182 string z=gcd(m[id],m1[id]); 183 string x=div(m[id],z,1); 184 string y=div(m1[id],z,1); 185 cout<<x<<"/"<<y<<endl; 186 } 187 return 0; 188 }