Bestcoder #32

2015-03-08 19:03:57

思路:这场打得不好... 怒降滚粗...

  T1紧张+粗心傻逼地 wa 了两发...

  T2知道怎么做... 但是wa到死 TAT,最后拿自己的错误点hack了一发,骗了点分... 

  T3、T4没看。

  赛后补了T2、T3、T4。

  T3,公式证明半天... 一个细节没考虑... wa好多发QAQ

  T4,一道挖掘隐藏条件的DP... 很水... 竟然放在最后,坑死了。

 

T1:三关键词排序...

 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 int n;
28 struct node{
29     int a,b,id;
30 }nd[105];
31 
32 bool cmp(node a,node b){
33     if(a.a - a.b == b.a - b.b){
34         if(a.b == b.b) return a.id < b.id;
35         return a.b < b.b;
36     }
37     return (a.a - a.b) > (b.a - b.b);
38 }
39 
40 int main(){
41     while(scanf("%d",&n) != EOF){
42     REP(i,n) scanf("%d%d",&nd[i].a,&nd[i].b),nd[i].id = i;
43     sort(nd + 1,nd + n + 1,cmp);
44     REP(i,n){
45         printf("%d%c",nd[i].id - 1,i == n ? '\n' : ' ');
46     }
47     }
48     return 0;
49 }
View Code

 

T2:维护前缀和,然后用set查找... 注意限时卡的很死... 尽量少开set和变量... set的操作也尽量少。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <set>
 6 #include <iostream>
 7 #include <algorithm>
 8 using namespace std;
 9 
10 int T,n,K;
11 long long sum[1000010];
12 set<long long> st;
13 int A[1000010];
14 
15 inline int Read(){
16     int x = 0,f = 1;char ch = getchar();
17     while(ch < '0' || ch > '9'){if(ch == '-')f = -1;ch = getchar();}
18     while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
19     return x * f;
20 }
21 
22 int main(){
23     T = Read();
24     for(int tt = 1; tt <= T; ++tt){    
25         st.clear();
26         n = Read();
27         K = Read();
28         for(int i = 1; i <= n; ++i) A[i] = Read();
29         bool flag = false;
30         for(int i = 1; i <= n; ++i){
31             if(i & 1)    sum[i] = sum[i - 1] + A[i];
32             else    sum[i] = sum[i - 1] - A[i];
33         }
34         for(int i = n; i >= 1; --i){
35             st.insert(sum[i]);
36             long long cur = (i & 1) ? sum[i - 1] + K : sum[i - 1] - K;
37             if(st.count(cur)){
38                 flag = true;
39                 break;
40             }
41         }
42         if(flag) printf("Case #%d: Yes.\n",tt);
43         else printf("Case #%d: No.\n",tt);
44     }
45     return 0;
46 }
View Code

 

T3:一个组合数学题... 将左括号、右括号看做向右走、向上走,然后就是一个从(0,0)走到(n/2,n/2)且不跨越y=x的问题,因为已经给出了部分前缀,

  所以等于从(x,y)到(n/2,n/2),再转化为从(0,0)走到(a,b)且不跨越y=x。这个种类数是C(a+b,b) - C(a+b,b-1)。

  简证:把问题“从(0,0)走到(a,b)且不跨越y=x的种数”,转化为“从(0,-1)走到(a,b-1)且不接触y=x的种数”。

       那么如何解决这个问题呢,我们先算出所有情况(C(a+b,b)),再减去有接触y=x的情况。

     ※设接触点为(k,k),我们发现(0,-1)->(k,k)的路径条数等于(-1,0)->(k,k)的路径条数。(即使接触点再多,我们都可以对称一下,转化到起点为(-1,0))

       那么从(0,-1)->(a,b-1)有接触y=x的情况总数为(-1,0)到(a,b-1)的路径数,为C(a+b,b-1)。

     综上,从(0,0)->(a,b)且不跨越y=x的种数为C(a+b,b) - C(a+b,b-1),证毕。

  

  注意:需要预先判断给出的前缀是否合法... 每时每刻都要判断左括号数是否 >= 右括号数。

 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 const ll mod = 1000000007LL;
27 const int MAXN = 1000000;
28 
29 int N;
30 ll fac[MAXN + 10],afac[MAXN + 10];
31 char s[MAXN + 10];
32 
33 ll Q_pow(ll x,ll y){
34     ll res = 1,X = x;
35     while(y){
36         if(y & 1) res = res * X % mod;
37         X = X * X % mod;
38         y >>= 1;
39     }
40     return res;
41 }
42 
43 void Pre(){
44     fac[0] = 1;
45     REP(i,MAXN)    fac[i] = fac[i - 1] * (ll)i % mod;
46     afac[MAXN] = Q_pow(fac[MAXN],mod - 2);
47     RFOR(i,MAXN - 1,0) afac[i] = afac[i + 1] * (i + 1) % mod;
48 }
49 
50 ll Comb(ll n,ll m){
51     if(n < m || m < 0) return 0;
52     return fac[n] * afac[m] % mod * afac[n - m] % mod;
53 }
54 
55 bool Judge(int &q,int &p){
56     if(N & 1) return false;
57     q = p = N / 2;
58     int len = strlen(s);
59     for(int i = 0; i < len; ++i){
60         if(s[i] == '(') q--;
61         else p--;
62         if(q > p) return false;
63     }
64     if(q < 0 || p < 0) return false;
65     return true;
66 }
67 
68 int main(){
69     Pre();
70     while(scanf("%d",&N) != EOF){
71         scanf("%s",s);
72         int q,p;
73         if(!Judge(q,p)){
74             printf("0\n");
75             continue;
76         }
77         ll ans = (Comb(p + q,q) - Comb(p + q,q - 1) + mod) % mod;
78         printf("%d\n",(int)ans);
79     }
80     return 0;
81 }
View Code

 

T4:DP,和以前一道cf题有点像,需要挖掘出“某些变量的变化范围不大”这个隐藏条件。

  因为x1~xn非严格递增,所以最大的xn不会超过sqrt(2×n),那么就可以枚举了,复杂度为n×sqrt(n)

  dp[i][j]表示用前i个数(0~i),组成和为j的情况数。dp[i][j] = dp[i][j - i] + dp[i - 1][j - i]。

 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 int T,n,m;
28 int dp[320][50010];
29 
30 int main(){
31     scanf("%d",&T);
32     REP(tt,T){
33         scanf("%d%d",&n,&m);
34         int top = sqrt(2.0 * n);
35         dp[0][0] = 1;
36         REP(i,top){
37             int up = min(n,i * n);
38             for(int j = i * (i + 1) / 2; j <= up; ++j){
39                 dp[i][j] = (dp[i][j - i] + dp[i - 1][j - i]) % m;
40                 //printf("dp[%d][%d] : %d\n",i,j,dp[i][j]);
41             }
42         }
43         int ans = 0;
44         REP(i,top) ans = (ans + dp[i][n]) % m;
45         printf("Case #%d: %d\n",tt,ans);
46     }
47     return 0;
48 }
View Code

 

posted @ 2015-03-08 20:07  Naturain  阅读(127)  评论(0编辑  收藏  举报