一個等腰直角三角形 ABC,角 ACB 是直角,AC=BC,點 C 在原點,讓肯定 A 和 B 的座標,使得三角形包含一個矩形,這個矩形一個角在原點,另外一個點在 (x, y) 處,而且三角形 ABC 的面積儘可能小ios
將 A B 兩點按照 x 座標從小到大輸出數組
A B 兩點必然在座標軸上,且線段 AB 通過點 (x, y),那麼簡單分類討論下就好了ide
交以前猶豫了一下,10分鐘才提交...spa
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 7 const int N=1000006; 8 9 int x, y; 10 11 int main() { 12 scanf("%d%d", &x, &y); 13 if(x>0 && y>0 || x<0 && y<0) { 14 if(x<0) { 15 printf("%d %d %d %d\n", x+y, 0, 0, x+y); 16 } 17 else { 18 printf("%d %d %d %d\n", 0, x+y, x+y, 0); 19 } 20 } 21 else { 22 if(x<0) { 23 printf("%d %d %d %d\n", x-y, 0, 0, y-x); 24 } 25 else { 26 printf("%d %d %d %d\n", 0, y-x, x-y, 0); 27 } 28 } 29 return 0; 30 }
在平面上有 2*m(1≤m≤105) 個一樣半徑的圓。他們編號分別爲 1~2*m,分上下兩排排列.3d
第 1 到 m 個圓的圓心座標分別爲:(2R-R, 0), (4R-R, 0),...,(2mR-R, 0)指針
第 m+1 到第 m+m 個圓的圓心座標分別爲:(2R-R, 2R), (4R-R, 2R),...,(2mR-R, 2R)code
有一隻 fly(蒼蠅?)在這個平面上運動了 m2 次,這 m2 次運動分別編號爲 0~(m2-1),編號爲 i 的那次運動從第 1+i/m 個圓的圓心運動到第 m+1+i%m 個圓的圓心,且走最短路,fly 走過的路徑必須包含在這 2*m 個圓肯定的區域中,不能走到外面的其餘地方blog
如今問,這隻 fly 的 m2 次運動中,每次運動走過的平均距離是多少get
典型的數學題,當時看見,菊花莫名其妙的一緊,腳趾頭都抓緊了......數學
觀察這 2*m 個圓的圓心座標不難發現,他們分紅了上下兩排,同一排相鄰的兩個圓相切,上下相鄰的兩個圓相切
再觀察 fly 每次運動走的圓的分佈規律,不難發現是每次選定一個下面的圓的圓心,分別以上面的圓的圓心爲目的點走一次最短路,因此總共有 m2 次運動
那麼一個最一般的想法就是:求出這 m2 次運動總共走過的距離
先看看最短路吧:
因爲每次必定是一個圓在下面,一個圓在上面,那麼能夠這樣搞:
當兩個圓相鄰時(列號差爲 0),最短路是 2R
當兩個圓的列號差爲 1 時,最短路是 2R+√2R
當兩個圓的列號差爲 2 時,最短路是 2R+2√2R
當兩個圓的列號差爲 3 時,最短路是 4R+2√2R
當兩個圓的列號差爲 4 時,最短路是 6R+2√2R
當兩個圓的列號差爲 5 時,最短路是 8R+2√2R
......
將他們存進一個數組 A 中,A[i] 表示列號差爲 i 的最短路長度
以 m 爲單位,看看每次運動的起始點和終止點
前 m 次運動:起始點始終是下面第 1 個圓,終止點從上面第 1 個圓變化到第 m 個圓
接下來的 m 次運動:起始點始終是下面第 2 個圓,終止點從上面第 1 個圓變化到第 m 個圓
再接下來的 m 次運動:起始點始終是下面第 3 個圓,終止點從上面第 1 個圓變化到第 m 個圓
......
細心的讀者在這裏的時候估計已經知道該怎麼作了,還沒想出來的朋友能夠接着往下看
從上面能夠看出:起始點是在不停的往前走的,而終止點始終是上面的圓從 1 到 m
咱們再以 m 爲單位,看看他們的距離和
前 m 次運動的距離和咱們能夠求出來:sum1=∑A[i]
那麼接下來的 m 次運動的距離和呢:sum2=sum-A[m-1]+A[1]
再接下來的的 m 次運動的距離和呢:sum3=sum2-A[m-2]+A[2]
第 4 個 m 次運動的距離和:sum4=sum3-A[m-3]+A[3]
......
相信看到這裏,你們都知道該怎麼作了 o(m) 的掃一遍,用兩個指針輔助,這樣就能夠求出來了
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 6 using namespace std; 7 8 const int N=100006; 9 10 int m; 11 double R, A[N]; 12 13 void init() { 14 A[0]=2, A[1]=2+sqrt(2); 15 for(int i=2; i<m; i++) A[i]=2*(i-1)+2*sqrt(2); 16 } 17 18 int main() { 19 scanf("%d%lf", &m, &R); 20 init(); 21 double ans=0; 22 for(int i=0; i<m; i++) { 23 ans+=A[i]; 24 } 25 int p1=1, p2=m-1; 26 double last=ans; 27 for(int i=1; i<m; i++) { 28 last=last-A[p2]+A[p1]; 29 ans+=last; 30 p1++, p2--; 31 } 32 printf("%lf\n", ans/m/m*R); 33 return 0; 34 }
給了 n(1≤n≤105) 個不一樣的數,要求選出一些數出來,使得這些數按位取與以後的數在二進制下,最低位的 1 所在的位儘可能高,若是有多重方案,輸出選取數的數量最大的一個方案
初一看很神,其實仔細想一下不難發現這題比 B 題還水...
考慮最後選取的數按位取與以後獲得的數,設爲 sum
要使 sum 在二進制下 1 的最低位最高,也就是說,這一位 1 之後,全部的數都應該是 0
想到這裏,反應比較快的讀者確定知道該怎麼作了
枚舉最低位,設爲 pos,先在全部數中選出二進制表示下,在 pos 位爲 1,的那些數,若是這些數按位取與,可以使得全部低於 pos 位的二進制位全爲 0,那麼這些數就是一個合法的答案,固然,若是咱們是從高位往地位枚舉的,這些數就是咱們最後的答案了
1 #include <cstring> 2 #include <cstdio> 3 #include <iostream> 4 5 using namespace std; 6 7 int A[100005], n; 8 bool vs[100005]; 9 10 int main() { 11 scanf("%d", &n); 12 for(int i=0; i<n; i++) scanf("%d", &A[i]); 13 for(int i=31; i>=0; i--) { 14 bool flag=1; 15 memset(vs, 0, sizeof vs); 16 for(int j=0; j<n; j++) if(A[j]&(1<<i)) vs[j]=1; 17 for(int pos=i-1; pos>=0 && flag; pos--) { 18 bool all=0; 19 for(int j=0; j<n && !all; j++) if(vs[j]) { 20 if(!(A[j]&(1<<pos))) all=1; 21 } 22 if(!all) flag=0; 23 } 24 if(flag) break; 25 } 26 int cnt=0; 27 for(int i=0; i<n; i++) if(vs[i]) cnt++; 28 printf("%d\n", cnt); 29 for(int i=0; i<n; i++) if(vs[i]) { 30 printf("%d", A[i]); 31 cnt--; 32 if(!cnt) printf("\n"); 33 else printf(" "); 34 } 35 return 0; 36 }