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 }
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 }
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 }
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 }