codeforces Rockethon 2015

2015-02-08 16:56:11

思路:大场!6500+人... (Orz.. 涨分降分都爽飞,TAT概率题好多)

  Rank:911(rating:1853(-9)).... 这个rank让我想到了某恐怖袭击?...

  改成了类似ACM的赛制,每个题目可能有多个测试点。只搞掉了A,B1,B2,G1....

  C题逗比地推导了好久数学,搞了将近一个多小时- =,赛后想到了一种暴力Dfs... 就过了QAQ

  反思:(1)比赛前放平心态,一个题目想好了再去敲,不然敲完再反复调试或频繁地换思路是很浪费时间的... (B1,B2各乱提交而wa一发是完全没有必要的)

       (2)养成编程思维,不要一味地侧重数学,充分利用高速计算的特点,学会如何暴力枚举和Dfs非常重要!(就如C题)

 

A:简而言之就是两个不断扔石子,最优的扔法当然是每次扔一个,那么只要比较一下n1和n2即可。(ps:一开始没怎么懂题意,学弟提醒的^_^)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define REV(i,n) for(int i=(n-1);i>=0;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 int n1,n2,k1,k2;
28 
29 int main(){
30     scanf("%d%d%d%d",&n1,&n2,&k1,&k2);
31     if(n1 > n2) printf("First\n");
32     else printf("Second\n");
33     return 0;
34 }
View Code

 

B:这题没有考虑暴力骗B1的分,直接打了一发正解。首先考虑1的位置,显然要使 f(p) 最大,1要放在最两边(这样覆盖到1的区间数最少)。

   然后考虑2的位置(排除了1),也是尽量放在两边...

   于是我们知道每个数(最后一个数除外)有两个位置可放,那么使得 f(p) 最大的总方案数为 2^(n-1)。

   然后就是类似康托展开的问题了。对于1,如果1放在首位,剩下的总方案数:2^(n-2),而1放在末尾的字典序必定大于1放在首位的字典序。那么判断m是否大于2^(n-2),如果大于,那么1放在末尾,且m -= 2^(n-2)。以此类推即可。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define REV(i,n) for(int i=(n-1);i>=0;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 ll n,m;
28 ll ans[1000];
29 ll fac[1000];
30 
31 int main(){
32     fac[0] = 1;
33     for(int i = 1; i <= 50; ++i)
34         fac[i] = fac[i - 1] * 2LL;
35     cin >> n >> m;
36     ll tmp = n;
37     ll p1 = 1,p2 = n;
38     for(int i = 1; i <= n; ++i){
39         if(m > fac[n - i - 1]){
40             m -= fac[n - i - 1];
41             ans[p2--] = i;
42         }
43         else{
44             ans[p1++] = i;
45         }
46     }
47     cout << ans[1];
48     for(int i = 2; i <= tmp; ++i)
49         cout << " " << ans[i];
50     cout << endl;
51     return 0;
52 }
View Code

 

C:这题... 看到别人普遍用bitmask枚举的... 本弱瞎搞了Dfs QAQ

  1:首先记录下能取的竞拍价的最小值和最大值,然后枚举最后的second-price auction(设为t)是几。

  2:然后枚举每个company出的竞拍价是大于 t,还是小于 t,还是等于 t。这个过程可以开个flag数组,用Dfs给每个company一个标记。

  3:对于每个Dfs终点,我们获得了各个公司的竞拍价与 t 的关系,然后判断一下这组关系是否可行(因为要使最后的付款为 t)

  4:对于所有可行关系组,我们就可以算出每个company与 t 产生该种关系的概率(如该公司:[4,7],t = 5 ,那么> t 的概率为 2/4),然后累加即可。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define REV(i,n) for(int i=(n-1);i>=0;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 int n,sc;
28 int L[10],R[10],len[10];
29 int tmax = 0,tmin = INF;
30 int flag[10];
31 double ans;
32 
33 bool Judge(){
34     FOR(i,1,n){
35         if(flag[i] == 1 && L[i] >= sc) return false;
36         if(flag[i] == 2 && (sc < L[i] || sc > R[i])) return false;
37         if(flag[i] == 3 && R[i] <= sc) return false;
38     }
39     int c[10];
40     MEM(c,0);
41     FOR(i,1,n) c[flag[i]]++;
42     if(c[2] >= 1 && (c[2] + c[3] >= 2) && c[3] <= 1) return true;
43     return false;
44 }
45 
46 void Dfs(int p){
47     if(p > n){
48         if(Judge()){
49             double p = 1.0;
50             FOR(i,1,n){
51                 if(flag[i] == 1)
52                     p *= 1.0 * (min(R[i],sc - 1) - L[i] + 1) / len[i];
53                 else if(flag[i] == 2)
54                     p /= (1.0 * len[i]);
55                 else
56                     p *= 1.0 * (R[i] - max(L[i],sc + 1) + 1) / len[i];
57             }
58             ans += 1.0 * sc * p;
59         }
60         return;
61     }
62     FOR(i,1,3){
63         flag[p] = i;
64         Dfs(p + 1);
65     }
66 }
67     
68 int main(){
69     scanf("%d",&n);
70     FOR(i,1,n){
71         scanf("%d%d",&L[i],&R[i]);
72         tmax = max(tmax,R[i]);
73         tmin = min(tmin,L[i]);
74         len[i] = R[i] - L[i] + 1;
75     }
76     ll sum = 0;
77     for(sc = tmin; sc <= tmax; ++sc){
78         MEM(flag,0);
79         Dfs(1);
80     }
81     printf("%.10f\n",ans);
82     return 0;
83 }
View Code

 

G1:没什么好的想法... 直接暴力Dfs枚举骗分了QAQ

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define REV(i,n) for(int i=(n-1);i>=0;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 int n,k;
28 int v[100];
29 int v2[100];
30 double  ans;
31 double sum;
32 
33 void Dfs(int s[100],int lev,double p){
34     if(lev > k){
35         //for(int i = 1; i <= n; ++i) printf("%d ",s[i]);
36         //puts("");
37         int cnt = 0;
38         for(int i = 2; i <= n; ++i)
39             for(int j = 1; j < i; ++j) if(s[j] > s[i])
40                 cnt++;
41         ans += 1.0 * cnt * p;
42         return;
43     }
44     int ts[100];
45     for(int i = 1; i <= n; ++i) ts[i] = s[i];
46     for(int l = 1; l <= n; ++l){
47         for(int r = l; r <= n; ++r){
48             int mid = getmid(l,r);
49             for(int k = l; k <= mid; ++k)
50                 swap(ts[k],ts[r - (k - l)]);
51             Dfs(ts,lev + 1,p / sum);
52             for(int i = 1; i <= n; ++i) ts[i] = s[i];
53         }
54     }
55 }
56 
57 
58 int main(){
59     scanf("%d%d",&n,&k);
60     FOR(i,1,n) scanf("%d",&v[i]);
61     sum = (n + 1) * n / 2;
62     Dfs(v,1,1.0);
63     printf("%.15f\n",ans);
64     return 0;
65 }
View Code

G2:递推想了半天... 虽然能看懂别人的代码... 但是自己想不到QAQ。

   敲了一发暴力+记忆化。枚举数对(i,j)在k次操作后保持相对位置不变的概率P(Dfs实现),然后判断val[i]与val[j]的关系。

   如果val[i] < val[j],那么ans += (1.0 - P)(原来顺序,要使产生逆序数,则要改变相对位置)

   如果val[i] > val[j],那么ans += P

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=1;i<=(n);++i)
17 #define REV(i,n) for(int i=(n);i>=1;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 double ans,dp[205][35][35];
28 int vis[205][35][35];
29 int n,k,v[35],tot;
30 
31 double Dfs(int l,int r,int m){
32     if(vis[m][l][r])
33         return dp[m][l][r];
34     if(m == 0){
35         if(l <= r) return 1.0;
36         return 0.0;
37     }
38     double res = 0.0;
39     REP(X,n) FOR(Y,X,n){
40         int tl = l,tr = r;
41         if(X <= tl && tl <= Y) tl = X + Y - tl;
42         if(X <= tr && tr <= Y) tr = X + Y - tr;
43         res += Dfs(tl,tr,m - 1) / (double)tot;
44     }
45     vis[m][l][r] = 1;
46     return dp[m][l][r] = res;
47 }
48 
49 int main(){
50     MEM(vis,0);
51     scanf("%d%d",&n,&k);
52     REP(i,n) scanf("%d",v + i);
53     tot = n * (n + 1) / 2;
54     REP(i,n) FOR(j,i + 1,n){
55         double res = Dfs(i,j,k);
56         if(v[i] < v[j]) ans += (1.0 - res);
57         else ans += res;
58     }
59     printf("%.15f\n",ans);
60     return 0;
61 }
View Code

 

posted @ 2015-02-08 05:22  Naturain  阅读(196)  评论(0编辑  收藏  举报