codeforces #287 div2(only)

2015-01-24 03:16:28

思路:仅div2场,4000+人....

  为了模拟div1气氛,先开了C,发现就是找规律乱搞....不幸细节写错wa两发,30+min才过的。。之后快速搞定了A、B。

  E题的话...知道就是个双权最短路...硬是被我写成记忆化搜索...后来才发现不是DAG,不能用DP求最短路!!!(太逗比了...)。。。赛后用Spfa搞掉了QAQ。。

  D题是个数位DP...

A:结构体排序

 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 MP(a,b) make_pair(a,b)
21 
22 typedef long long ll;
23 typedef pair<int,int> pii;
24 const int INF = (1 << 30) - 1;
25 
26 int n,k,an[1000];
27 struct node{
28     int a,id;
29 }no[1000];
30 
31 bool cmp(node aa,node bb){
32     return aa.a < bb.a;
33 }
34 
35 int main(){
36     scanf("%d%d",&n,&k);
37     REP(i,n){
38         scanf("%d",&no[i].a);
39         no[i].id = i;
40     }
41     sort(no + 1,no + n + 1,cmp);
42     int ans = 0;
43     REP(i,n){
44         k -= no[i].a;
45         if(k < 0) break;
46         ans++;
47         an[i] = no[i].id;
48     }
49     printf("%d\n",ans);
50     if(ans == 0) return 0;
51     REP(i,ans - 1) printf("%d ",an[i]);
52     printf("%d\n",an[ans]);
53     return 0;
54 }
View Code

B:简单几何...圆心距离/直径,然后向上取整即可..注意下精度

 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 MP(a,b) make_pair(a,b)
21 
22 typedef long long ll;
23 typedef pair<int,int> pii;
24 const int INF = (1 << 30) - 1;
25 
26 ll r,a,b,c,d;
27 
28 int main(){
29     scanf("%I64d%I64d%I64d%I64d%I64d",&r,&a,&b,&c,&d);
30     double dis = sqrt(1.0 * (c - a) * (c - a) + 1.0 * (d - b) * (d - b));
31     ll ans = dis / (2.0 * r);
32     if(fabs(dis - 2.0 * r * ans) > 1e-8) ++ans;
33     printf("%I64d\n",ans);
34     return 0;
35 }
View Code

C:找规律,用h开始,判断exit是在左半子树还是右半子树,然后将h-1再判断...直到h=0,过程中计数即可(开long long)

  注意:算2^50次方是应该1LL<<50,这个LL不能漏掉!

 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 MP(a,b) make_pair(a,b)
21 
22 typedef long long ll;
23 typedef pair<int,int> pii;
24 const int INF = (1 << 30) - 1;
25 
26 ll h,n,ans;
27 ll fac[100];
28 
29 int main(){
30     fac[0] = 1;
31     ll b = 2;
32     REP(i,50){
33         fac[i] = b;
34         b <<= 1;
35     }
36     scanf("%I64d%I64d",&h,&n);
37     ans = 0;
38     int f = 0;
39     while(h >= 1){
40         if(f == 0){ //first left
41             if(n > fac[h - 1]){ //r
42                 ans += fac[h] - 1;
43                 n -= fac[h - 1];
44                 f = 0;
45             }
46             else{ //l
47                 f = 1;
48             }
49         }
50         else{ //first right
51             if(n <= fac[h - 1]){ //l
52                 ans += fac[h] - 1;
53                 f = 1;
54             }
55             else{ //r
56                 n -= fac[h - 1];
57                 f = 0;
58             }
59         }
60         h--;
61         ans++;
62     }
63     printf("%I64d\n",ans);
64      return 0;
65 }
View Code

D:从最低位开始放数...记忆化中:p表示放第几个数,r表示当前数模k的余数,f表示当前数是否已经存在后缀mod k == 0。

  这里考虑:如果已经存在某一后缀mod k == 0,那么前面的一些数就可以随便放了...(当然第一个数不能是0)

 1 #include <cstdio>
 2 #include <cstring>
 3 #define MEM(a,b) memset(a,b,sizeof(a))
 4 #define REP(i,n) for(int i=1;i<=(n);++i)
 5 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
 6 typedef long long ll;
 7 
 8 ll n,k,m;
 9 ll dp[1010][110][2],pw[1010],PW[1010];
10 
11 ll Solve(ll p,ll r,int f){
12     if(p <= 0) return f;
13     if(~dp[p][r][f]) return dp[p][r][f];
14     if(f) return (9LL * PW[p - 1]) % m;
15     ll res = 0;
16     FOR(i,(p == 1) ? 1 : 0,9){
17         ll nr = (r + (ll)i * pw[n - p]) % k;
18         res = (res + Solve(p - 1,nr,f || (!nr && i))) % m;
19     }
20     return dp[p][r][f] = res;
21 }
22 
23 int main(){
24     scanf("%I64d%I64d%I64d",&n,&k,&m);
25     pw[0] = PW[0] = 1;
26     REP(i,n) pw[i] = (pw[i - 1] * 10) % k,PW[i] = (PW[i - 1] * 10) % m;
27     MEM(dp,-1);
28     printf("%I64d\n",Solve(n,0,0));
29     return 0;
30 }

 

E:直接跑一遍最短路,需要注意的是边是双权的,所以用pair来存,保证first较小的同时保证second较小,那么就pair之间直接比就行~

 最后关于边的标记...可以开map,也可以自己搞个标记数组,随便啦....

  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 MP(a,b) make_pair(a,b)
 21 
 22 typedef long long ll;
 23 typedef pair<int,int> pii;
 24 const int INF = (1 << 30) - 1;
 25 const int maxn = 100010;
 26 
 27 int n,m;
 28 int first[maxn],ecnt;
 29 int inq[maxn],pre[maxn];
 30 pii dis[maxn];
 31 queue<int> Q;
 32 map< pii,int> mp;
 33 
 34 struct edge{
 35     int u,v,next,z;
 36 }e[maxn << 2];
 37 
 38 void Add_edge(int u,int v,int zz){
 39     e[++ecnt].next = first[u];
 40     e[ecnt].u = u;
 41     e[ecnt].v = v;
 42     e[ecnt].z = zz;
 43     first[u] = ecnt;
 44 }
 45 
 46 void Spfa(int st){
 47     REP(i,n) dis[i] = MP(INF,0);
 48     dis[st] = MP(0,0);
 49     while(!Q.empty()) Q.pop();
 50     MEM(inq,0);
 51     Q.push(1);
 52     while(!Q.empty()){
 53         int x = Q.front(); Q.pop();
 54         inq[x] = 0;
 55         for(int i = first[x]; ~i; i = e[i].next){
 56             int v = e[i].v;
 57             if(dis[v] > MP(dis[x].first + 1,dis[x].second + !e[i].z)){
 58                 dis[v] = MP(dis[x].first + 1,dis[x].second + !e[i].z);
 59                 pre[v] = i;
 60                 if(inq[v] == 0){
 61                     inq[v] = 1;
 62                     Q.push(v);
 63                 }
 64             }
 65         }
 66     }
 67 }
 68 
 69 int main(){
 70     int a,b,c,tm = 0;
 71     scanf("%d%d",&n,&m);
 72     MEM(first,-1);
 73     ecnt = 0;
 74     REP(i,m){
 75         scanf("%d%d%d",&a,&b,&c);
 76         Add_edge(a,b,c);
 77         Add_edge(b,a,c);
 78         tm += c;
 79     }
 80     Spfa(1);
 81     int sum = 0,cnt = 0;
 82     int pos = n;
 83     while(pos != 1){
 84         int p = e[pre[pos]].u;
 85         mp[MP(pos,p)] = 1;
 86         mp[MP(p,pos)] = 1;
 87         if(e[pre[pos]].z == 0) ++cnt;
 88         sum++;
 89         pos = p;
 90     }
 91     printf("%d\n",tm - sum + cnt + cnt);
 92     REP(i,ecnt) if(e[i].u < e[i].v){
 93         if(mp.find(MP(e[i].u,e[i].v)) == mp.end() && e[i].z)
 94             printf("%d %d %d\n",e[i].u,e[i].v,0);
 95         else if(mp.find(MP(e[i].u,e[i].v)) != mp.end() && e[i].z == 0){
 96             printf("%d %d %d\n",e[i].u,e[i].v,1);
 97         }
 98     }
 99     return 0;
100 }

 

posted @ 2015-01-24 03:26  Naturain  阅读(112)  评论(0编辑  收藏  举报