hdu 6561 High Priestess

2018 CCPC 吉林站 G题
用不超过1e4个1Ω的电阻,通过多次并联或串联,构造出一个接近目标大小的等效电阻。目标电阻为(0.1<=r<=0.9)的实数,构造出的等效电阻与目标大小相差不能超过1e-7。

这题比较假,标算说是直接拆成几个埃及分数之和就好了,也就是把几组并联的电阻再串起来。当然随便弄会用掉太多电阻,所以随机一下或者是暴力一下,数据比较弱就过了。

当时想的是连分数分解,大部分情况下用不了多少电阻。但是对于特殊数据,像0.1000001这种会挂,暴力打表发现有几千个这样的数就没敢写。后来发现数据比较水根本没这种情况可以过,但中间还因为分解的精度问题wa了很多遍。(以后连分数分解一定要写成有理分数做gcd的。)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. typedef double db;
  5.  
  6. int d[100],dc;
  7. db x;
  8.  
  9. bool ok(){
  10. 	db r=d[dc-1];
  11. 	for (int i=dc-2;i>=0;i--){
  12. 		r=d[i]+1/r;
  13. 	}
  14. 	//cout<<1/r-x<<'\n';
  15. 	return fabs(1/r-x)<9e-8;
  16. }
  17.  
  18. int al[50000],ar[50000],ap[50000],ac;
  19.  
  20. int main()
  21. {
  22. 	int kase=0; int T; cin>>T;
  23. 	//for (x=0.1;x<0.9;x+=0.0000001){
  24. 	while (cin>>x){
  25. 		db r=x;
  26. 		dc=0;
  27. 		do{
  28. 			r=1/r;
  29. 			d[dc++]=(int)(r+1e-13);
  30. 			r-=(int)(r+1e-13);
  31. 		}while (!ok());
  32. 		kase++;
  33. 		//for (int i=0;i<dc;i++) cout<<d[i]<<' '; cout<<'\n';
  34. 		int un=accumulate(d,d+dc,0),u0=0;
  35. 		if (d[dc-1]==1){
  36. 			dc--;
  37. 			d[dc-1]++;
  38. 		}
  39. 		printf("Case %d:\n%d ",kase,un);
  40. 		ac=0;
  41. 		for (int i=dc-1;i>=0;i--){
  42. 			if (i==dc-1){
  43. 				al[ac]=0,ar[ac]=1,ap[ac]=!(i&1),ac++;
  44. 				u0=2;
  45. 				for (int j=0;j<d[i]-2;j++)
  46. 					al[ac]=u0++,ar[ac]=un++,ap[ac]=!(i&1),ac++;
  47. 			}
  48. 			else{
  49. 				for (int j=0;j<d[i];j++)
  50. 					al[ac]=u0++,ar[ac]=un++,ap[ac]=!(i&1),ac++;
  51. 			}
  52. 		}
  53. 		printf("%d\n",ac);
  54. 		for (int i=0;i<ac;i++){
  55. 			printf("%d %d %d\n",ap[i],al[i],ar[i]);
  56. 		}
  57. 	}
  58. 	//cout<<cnt<<'\n';
  59. 	return 0;
  60. }

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注