Codeforces Round #195 A B C 三題合集 (Div. 2)

 

A 題 Vasily the Bear and Triangle

 

題目大意

 

一個等腰直角三角形 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 }
A

 

 

 

B 題 Vasily the Bear and Fly

 

題目大意

 

在平面上有 2*m(1m105) 個一樣半徑的圓。他們編號分別爲 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+22R

    

    當兩個圓的列號差爲 3 時,最短路是 4R+22R

    

    當兩個圓的列號差爲 4 時,最短路是 6R+22R

    

    當兩個圓的列號差爲 5 時,最短路是 8R+22R

    ......

將他們存進一個數組 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 }
B

 

 

 

C 題 Vasily the Bear and Sequence

 

題目大意

 

給了 n(1n105) 個不一樣的數,要求選出一些數出來,使得這些數按位取與以後的數在二進制下,最低位的 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 }
C
相關文章
相關標籤/搜索