CF #277.5 div2

2014-11-20 22:41:06

总结:这场cf总共6题,比赛艹了四题,成功帮助绿名小号回蓝-。-‘,赛后补完。

A:问排序的交换方案,并输出,这种模拟题在cf不少见,就是比谁更暴力!

 1 /*************************************************************************
 2     > File Name: a.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Mon 17 Nov 2014 11:37:05 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int n;
28 int t[3010];
29 int ans[3010][2],cnt;
30 
31 int main(){
32     scanf("%d",&n);
33     for(int i = 1; i <= n; ++i){
34         scanf("%d",t + i);
35     }
36 
37     for(int i = 1; i <= n; ++i){
38         int tmin = INF,pos;
39         for(int j = i; j <= n; ++j){
40             if(t[j] < tmin){
41                 tmin = t[j];
42                 pos = j;
43             }
44         }
45         if(pos != i){
46             int tmp = t[i];
47             t[i] = t[pos];
48             t[pos] = tmp;
49             ans[++cnt][0] = i;
50             ans[cnt][1] = pos;
51         }
52     }
53     printf("%d\n",cnt);
54     for(int i = 1; i <= cnt; ++i){
55         printf("%d %d\n",ans[i][0] - 1,ans[i][1] - 1);
56     }
57     return 0;
58 }
View Code

B:看似一道匹配题,比赛中第一反应就是排序贪心,其实想想就知道很好证明,能配则配肯定是最优解。

 1 /*************************************************************************
 2     > File Name: b.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Mon 17 Nov 2014 11:51:09 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int n,m;
28 int a[105],b[105];
29 
30 int main(){
31     scanf("%d",&n);
32     for(int i = 1; i <= n; ++i)
33         scanf("%d",&a[i]);
34     scanf("%d",&m);
35     for(int i = 1; i <= m; ++i)
36         scanf("%d",&b[i]);
37     sort(a + 1,a + n + 1);
38     sort(b + 1,b + m + 1);
39     int vis[105];
40     memset(vis,0,sizeof(vis));
41     int ans = 0;
42     for(int i = 1; i <= n; ++i){
43         for(int j = 1; j <= m; ++j){
44             if(!vis[j] && abs(a[i] - b[j]) <= 1){
45                 vis[j] = 1;
46                 ++ans;
47                 break;
48             }
49         }
50     }
51     printf("%d\n",ans);
52     return 0;
53 }
View Code

C:贪心题,智商下线wa了几发,最后写了个无敌暴力的短程序。注意特判:s > 9m 和 s == 0 && m != 1 的情况

 1 /*************************************************************************
 2     > File Name: c.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Mon 17 Nov 2014 11:59:26 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int m,s;
28 int ans[105];
29 int ans2[105];
30 
31 int main(){
32     scanf("%d%d",&m,&s);
33     if(s > 9 * m){
34         printf("-1 -1\n");
35         return 0;
36     }
37     if(s == 0 && m != 1){
38         printf("-1 -1\n");
39         return 0;
40     }
41     int k = s;
42     for(int i = 1; i <= m; ++i){
43         while(ans[i] < 9 && k > 0){
44             ans[i]++;
45             --k;
46         }
47     }
48     ans2[1] = min(1,s);
49     k = s - 1;
50     for(int i = m; i >= 1; --i){
51         while(ans2[i] < 9 && k > 0){
52             ans2[i]++;
53             --k;
54         }
55     }
56     for(int i = 1; i <= m; ++i) printf("%d",ans2[i]);
57     printf(" ");
58     for(int i = 1; i <= m; ++i) printf("%d",ans[i]);
59     puts("");
60     return 0;
61 }
View Code

D:搜索暴力题,比赛时花了5分钟看题意5分钟想思路,其实就是枚举每个点,然后从那个点出发,走两步(也就是Dfs深度为2),将走两步到的点的vis值加1,最后根据排列组合思想可知:设一个点作为走两步的终点被走到k次,那么当前枚举点和这个终点间形成k * (k - 1) / 2种菱形(除以二可以放在最后,以提高效率)

 1 /*************************************************************************
 2     > File Name: d.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Tue 18 Nov 2014 12:47:37 AM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 const int maxn = 3010;
27 
28 int n,m;
29 int first[maxn],next[maxn * 10],ver[maxn * 10],ecnt;
30 ll vis[maxn];
31 
32 void Init(){
33     memset(first,-1,sizeof(first));
34     ecnt = 0;
35 }
36 
37 void Add_edge(int u,int v){
38     next[++ecnt] = first[u];
39     ver[ecnt] = v;
40     first[u] = ecnt;
41 }
42 
43 void Dfs(int p,int dep){
44     if(dep == 2){
45         vis[p]++;
46         return;
47     }
48     for(int i = first[p]; i != -1; i = next[i]){
49         int v = ver[i];
50         Dfs(v,dep + 1);
51     }
52 }
53 
54 int main(){
55     Init();
56     int a,b;
57     scanf("%d%d",&n,&m);
58     for(int i = 1; i <= m; ++i){
59         scanf("%d%d",&a,&b);
60         Add_edge(a,b);
61     }
62     ll ans = 0;
63     for(int i = 1; i <= n; ++i){
64         memset(vis,0,sizeof(vis));
65         Dfs(i,0);
66         for(int j = 1; j <= n; ++j) if(i != j){
67             ans += vis[j] * (vis[j] - 1);
68         }
69     }
70     printf("%I64d\n",ans / 2);
71     return 0;
72 }
73     
View Code

E:01分数规划题,没接触过,比赛时看都没看,其实就是DP时用上分数规划,现在想想学过分数规划的基本都能A出来QAQ。

  二分枚举 d[i] = a[i] - L * b[i] 中的L,然后就是普通O(n^2)的DP,注意DP过程中用的d[i]的值,然后判断终点dp[n]的DP值的正负再改变二分边界即可。

 1 /*************************************************************************
 2     > File Name: e.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Wed 19 Nov 2014 11:32:19 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 const double eps = 1e-8;
27 
28 int n;
29 double l,x[1010],b[1010];
30 double dis[1010][1010];
31 double dp[1010];
32 int pre[1010],ans[1010];
33 
34 bool Check(double v){
35     for(int i = 1; i <= n; ++i){
36         dp[i] = INF;
37         for(int j = 0; j < i; ++j){
38             double tmp = dp[j] + dis[j][i];
39             if(tmp < dp[i]){
40                 dp[i] = tmp;
41                 pre[i] = j;
42             }
43         }
44         dp[i] -= v * b[i];
45     }
46     if(dp[n] <= 0) return true;
47     return false;
48 }
49 
50 int main(){
51     scanf("%d%lf",&n,&l);
52     for(int i = 1; i <= n; ++i){
53         scanf("%lf%lf",x + i,b + i);
54     }
55     for(int i = 0; i <= n; ++i){
56         for(int j = 0; j < i; ++j){
57             dis[j][i] = sqrt(fabs(x[i] - x[j] - l));
58         }
59     }
60     double low = 0,high = 1000.0;
61     while(fabs(high - low) > eps){
62         double mid = getmid(low,high);
63         if(Check(mid))
64             high = mid;
65         else
66             low = mid;
67     }
68     int pos = 0,p = n;
69     while(p){
70         ans[++pos] = p;
71         p = pre[p];
72     }
73     for(int i = pos; i >= 1; --i){
74         if(i != pos) printf(" ");
75         printf("%d",ans[i]);
76     }
77     puts("");
78     return 0;
79 }

F:就是个DP,cf果然是dp大户啊。。。从m+1行开始枚举到n行,一行放两个1,设dp[i][j]表示这一行还有i个列没有放过1,还有j个列只放了1个1。

  方法1:挑两个i的列放,dp[i - 2][j + 2] += dp[i][j]

  方法2:挑两个j的列放,dp[i][j - 2] += dp[i][j]

  方法3:挑一个i的列,一个j的列放,dp[i - 1][j] += dp[i][j]

版本1:滚动数组,自己瞎搞的三维dp,530ms,慢到爆。

 1 /*************************************************************************
 2     > File Name: f.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Wed 19 Nov 2014 08:06:56 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int n,m;
28 char s[505];
29 int num[505];
30 ll mod,dp[2][505][505];
31 
32 int main(){
33     scanf("%d%d%I64d",&n,&m,&mod);
34     for(int i = 1; i <= m; ++i){
35         scanf("%s",s + 1);
36         for(int j = 1; j <= n; ++j){
37             if(s[j] == '1')
38                 num[j]++;
39         }
40     }
41     int c0 = 0,c1 = 0;
42     for(int j = 1; j <= n; ++j){
43         if(num[j] == 0) ++c0;
44         else if(num[j] == 1) ++c1;
45     }
46     int now = 0;
47     dp[now][c0][c1] = 1;
48     for(int k = m; k < n; ++k){
49         for(int i = 0; i <= n; ++i){
50             for(int j = 0; j <= n; ++j){
51                 if(dp[now][i][j] == 0)
52                     continue;
53                 if(i >= 2)
54                     dp[now ^ 1][i - 2][j + 2] = (dp[now ^ 1][i - 2][j + 2] + dp[now][i][j] * i * (i - 1) / 2) % mod;
55                 if(j >= 2)
56                     dp[now ^ 1][i][j - 2] = (dp[now ^ 1][i][j - 2] + dp[now][i][j] * j * (j - 1) / 2) % mod;
57                 if(i >= 1 && j >= 1)
58                     dp[now ^ 1][i - 1][j] = (dp[now ^ 1][i - 1][j] + dp[now][i][j] * i * j) % mod;
59             }
60         }
61         now ^= 1;
62     }
63     printf("%I64d\n",dp[now][0][0]);
64     return 0;
65 }
View Code

版本2:;利用i单调递减性优化到O(n^2)的,46ms,可以接受。

 1 /*************************************************************************
 2     > File Name: f.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Wed 19 Nov 2014 08:06:56 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int n,m;
28 char s[505];
29 int num[505];
30 ll mod,dp[505][505];
31 
32 int main(){
33     scanf("%d%d%I64d",&n,&m,&mod);
34     for(int i = 1; i <= m; ++i){
35         scanf("%s",s + 1);
36         for(int j = 1; j <= n; ++j){
37             if(s[j] == '1')
38                 num[j]++;
39         }
40     }
41     int c0 = 0,c1 = 0;
42     for(int j = 1; j <= n; ++j){
43         if(num[j] == 0) ++c0;
44         else if(num[j] == 1) ++c1;
45     }
46     dp[c0][c1] = 1;
47     for(int i = n; i >= 0; --i){
48         for(int j = n; j >= 0; --j){
49             if(dp[i][j] == 0)
50                 continue;
51             if(i >= 2)
52                 dp[i - 2][j + 2] = (dp[i - 2][j + 2] + dp[i][j] * i * (i - 1) / 2) % mod;
53             if(j >= 2)
54                 dp[i][j - 2] = (dp[i][j - 2] + dp[i][j] * j * (j - 1) / 2) % mod;
55             if(i >= 1 && j >= 1)
56                 dp[i - 1][j] = (dp[i - 1][j] + dp[i][j] * i * j) % mod;
57         }
58     }
59     printf("%I64d\n",dp[0][0]);
60     return 0;
61 }

 

posted @ 2014-11-20 23:00  Naturain  阅读(128)  评论(0编辑  收藏  举报