[luogu1737]旷野大计算
(以下题解仅描述方法,具体实现参考代码)
任务1
限制:$6$个
利用分配律优化即可
任务2
限制:$6$个
利用$17=2^{4}+1$优化即可
任务3
限制:$6$个
当$|x|$足够大时,$S(x)$仅取决于$x$的正负性
根据此性质,有$f_{1}(x)=S(2^{\inf_{1}}x)=\begin{cases}1&x>0\\0.5&x=0\\0&x<0\end{cases}$($2$个)
关于$\inf_{1}$,即要求$\frac{1}{1+e^{\frac{2^{\inf_{1}}}{10^{9}}}}\le 10^{-100}$(注意到$S(x)+S(-x)=1$),解得${\inf_{1}}\ge 38$
任务4
限制:$14$个
当$|x|\le 10^{-50}$时,在$x=0$处泰勒展开,可得$S(x)=\frac{1}{4}x+\frac{1}{2}$
用"足够大/小"区分正/负,有$f_{2}(x)=2^{\inf_{2}}f_{1}(x+{\rm eps})=\begin{cases}2^{\inf_{2}}&x\ge 0\\0&x<0\end{cases}$($4$个)
在此基础上,有$f_{3}(x)=x+f_{2}(x)-2^{\inf_{2}+1}\left(S\big(f_{2}(x)+\frac{x}{2^{\inf_{2}-2}}\big)-0.5\right)=|x|$($12$个)
关于${\rm eps}$,即要求${\rm eps}<10^{-9}$,可取$10^{-10}$(另外,这会修改$\inf_{1}$的条件,解得$\inf_{1}\ge 42$)
关于$\inf_{2}$,即要求$\begin{cases}\frac{10^{9}}{2^{\inf_{2}-2}}\le 10^{-50}\\10^{-90}2^{\inf_{2}}<10^{-9}\end{cases}$,解得$\inf_{2}\in [198,269]$
任务5
限制:$95$个
每次$\times 2+x$即可,并在最高位仅输入,即$1+3\times 31+1=95$个
任务6
限制:$190$个
从大到小枚举$i\in [0,32)$,第$i$位即$f_{1}(x-2^{i}+{\rm eps})$,并用$x$减去$2^{i}\times $即可
$f_{1}$的左移可以仅进行一次,并在最低位仅右移输出,即$2+6\times 31+2=190$个
任务7
限制:$605$个
结合前两个任务,问题即需实现单个$0,1$的异或
仅需在相加后为$2$时减$2$,有$f_{6}(x)=x-2\times f_{1}(x-2+{\rm eps})=\begin{cases}x-2&x=2\\x&x=0,1\end{cases}$($6$个)
综上,即$2+(190-33)\times 2+7\times 32+(95-33)+1=603$个
任务8
限制:$7$个
取$x_{0}$满足$S'(x_{0})=\frac{1}{10}$,解得$e^{-x_{0}}=4\pm \sqrt{15}$
不妨取$4-\sqrt{15}$,即$x_{0}=\ln (4+\sqrt{15}),S(x_{0})=\frac{5+\sqrt{15}}{10}$
当$|x-x_{0}|\le 10^{-50}$,在$x=x_{0}$处泰勒展开,即$S(x)=\frac{x-x_{0}}{10}+S(x_{0})$
在此基础上,有$f_{7}(x)=2^{\inf_{2}}\left(S(\frac{x}{2^{\inf_{2}}}+x_{0})-S(x_{0})\right)=\frac{x}{10}$($5$个)
任务9
限制:$3000$个
对于两数$x,y$,考虑在$x>y$时交换两数,等价于$\begin{cases}x'=x+\min(y-x,0)\\y'=y-\min(y-x,0)\end{cases}$
仅需稍微改动$f_{3}$,有$f_{8}(x)=2^{\inf_{2}+1}\left(S\big(f_{2}(x)+\frac{x}{2^{\inf_{2}-1}}\big)-0.5\right)-f_{2}(x)=\min(x,0)$($11$个)
在此基础上,交换两数即$16$个,用冒泡排序实现,即$16+{16\choose 2}\times 16+16=1952$个
另外,用双调排序实现(具体参考这里),仅需$50$次交换,即$16+50\times 16+16=1312$个
任务10
限制:$2000$个
关于乘法,将其中一个数按二进制拆分,即需求形如$p\times 2^{i}\times x$的值
仅需稍微改动$f_{2}$和$f_{3}$,有$\begin{cases}f_{9}(x)=(p-1)2^{\inf_{2}+i-1}\\f_{10}(x)=2^{\inf_{2}+i}\left(S\big(f_{9}(x)+\frac{x}{2^{\inf_{2}-2}}\big)-0.5\right)-f_{9}(x)=p\times 2^{i}\times x\end{cases}$($9$个)
关于取模,考虑从高位到低位依次求解,取$p=f_{1}(x-2^{i}m+{\rm eps})$并统一取负&左移优化即可
综上,即$4+(190-33)+(10\times 31+9)+14\times 64+2=1378$个
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL __int128 4 #define mid (l+r>>1) 5 const int inf1=50; 6 const int inf2=200; 7 const string eps="0.0000000001"; 8 const string feps=".9999999999"; 9 const string x10="2.063437068895560546727281172620131871456591449883392499836032692765902842847409911780353006"; 10 const string Sx10="0.887298334620741688517926539978239961083292170529159082658757376611348309193697903351928738"; 11 const string Pw="112589.9906842624"; 12 int T,n,a[32],b[32];string pw[32]; 13 void init(){ 14 for(int i=0;i<32;i++){ 15 for(LL j=((LL)1<<inf1+i)-112590;j;j/=10)pw[i]=(char)(j%10+'0')+pw[i]; 16 pw[i]="-"+pw[i]+".0093157376"; 17 } 18 } 19 void P(string a){ 20 n++,printf("%s\n",a.c_str()); 21 } 22 void P(string a,int x){ 23 P(a+" "+to_string(x)); 24 } 25 void P(string a,int x,int y){ 26 P(a+" "+to_string(x)+" "+to_string(y)); 27 } 28 void P(string a,int x,string b){ 29 P(a+" "+to_string(x)+" "+b); 30 } 31 void f1(int m){//2 32 P("<",m,inf1),P("S",n); 33 } 34 void f2(int m){//4 35 P("C",m,eps),f1(n),P("<",n,inf2); 36 } 37 void f3(int m){//12 38 f2(m),P(">",m,inf2-2),P("+",n-1,n),P("S",n),P("C",n,"-0.5"),P("<",n,inf2+1),P("-",n),P("+",m,n-6),P("+",n-1,n); 39 } 40 void f4(int *a){//62 41 int m=a[31]; 42 for(int i=30;i>=0;i--)P("<",m,1),P("+",a[i],n),m=n; 43 } 44 void f5(int m,int *a){//157 45 P("<",m,inf1),m=n; 46 for(int i=31;i;i--)P("C",m,pw[i]),P("S",n),a[i]=n,P("<",n,inf1+i),P("-",n),P("+",m,n),m=n; 47 P(">",m,inf1),a[0]=n; 48 } 49 void f6(int m){//6 50 P("C",m,"-1"+feps),f1(n),P("<",n,1),P("-",n),P("+",m,n); 51 } 52 void f7(int m){//5 53 P(">",m,inf2),P("C",n,x10),P("S",n),P("C",n,"-"+Sx10),P("<",n,inf2); 54 } 55 void f8(int m){//11 56 f2(m),P(">",m,inf2-1),P("+",n-1,n),P("S",n),P("C",n,"-0.5"),P("<",n,inf2+1),P("-",n-5),P("+",n-1,n); 57 } 58 void solveB(int l,int r){ 59 if (l==r)return; 60 for(int i=l;i<=mid;i++){ 61 int j=i+mid-l+1,x=a[i],y=a[j]; 62 P("-",x),P("+",y,n),f8(n),P("+",x,n),a[i]=n,P("-",n-1),P("+",y,n),a[j]=n; 63 } 64 solveB(l,mid),solveB(mid+1,r); 65 } 66 void solve(int l,int r){ 67 if (l==r)return; 68 solve(l,mid),solve(mid+1,r); 69 reverse(a+mid+1,a+r+1),solveB(l,r); 70 } 71 void f9(int m,int p,int i){//2 72 P("C",p,"-1"),P("<",n,inf2+i-1); 73 } 74 void f10(int m,int p,int i){//9 75 f9(m,p,i),P(">",m,inf2-2),P("+",n-1,n),P("S",n),P("C",n,"-0.5"),P("<",n,inf2+i),P("-",n-5),P("+",n-1,n); 76 } 77 int main(){ 78 scanf("%d",&T),init(); 79 if (T==1)P("I"),P("I"),P("+ 1 2"),P("- 3"),P("< 4 1"),P("O 5"); 80 if (T==2)P("I"),P("< 1 4"),P("+ 1 2"),P("- 3"),P("S 4"),P("O 5"); 81 if (T==3)P("I"),f1(1),P("< 3 1"),P("C 4 -1"),P("O 5"); 82 if (T==4)P("I"),f3(1),P("O 13"); 83 if (T==5){ 84 for(int i=31;i>=0;i--)P("I"),a[i]=n; 85 f4(a),P("O",n); 86 } 87 if (T==6){ 88 P("I"),f5(1,a); 89 for(int i=31;i>=0;i--)P("O",a[i]); 90 } 91 if (T==7){ 92 P("I"),P("I"),f5(1,a),f5(2,b); 93 for(int i=0;i<32;i++)P("+",a[i],b[i]),f6(n),a[i]=n; 94 f4(a),P("O",n); 95 } 96 if (T==8)P("I"),f7(1),P("O 6"); 97 if (T==9){ 98 for(int i=0;i<16;i++)P("I"),a[i]=n; 99 if (0){//冒泡排序 100 for(int i=0;i<16;i++) 101 for(int j=15;j>i;j--){ 102 int x=a[j-1],y=a[j]; 103 P("-",x),P("+",y,n),f8(n),P("+",x,n),a[j-1]=n,P("-",n-1),P("+",y,n),a[j]=n; 104 } 105 } 106 else solve(0,15);//双调排序 107 for(int i=0;i<16;i++)P("O",a[i]); 108 } 109 if (T==10){ 110 P("I"),P("I"),P("I"),P("-",3),f5(1,a),f10(2,a[0],inf1); 111 int m=n; 112 for(int i=1;i<32;i++)f10(2,a[i],inf1+i),P("+",m,n),m=n; 113 for(int i=63;i>=0;i--)P("<",4,inf1+i),P("+",m,n),P("C",n,Pw),P("S",n),f10(4,n,inf1+i),P("+",m,n),m=n; 114 P(">",m,inf1),P("O",n); 115 } 116 return 0; 117 }