CF337
集训第一场个人赛,感觉自己后劲不足,虚的很。
虽然最后没看题解出了所有的题,但是我这速度这也太慢了。
A
排个序
B
需要特殊考虑0/1的情况,自己还是不大行,考虑不全面
C
贪心的想,一定是错在后面更划算。然后问题就是前面连续的怎么算。
假设n为k的倍数
F[n] = (F[n-k] + k) * 2;
F[n] = ((F[n-2k]+k)*2 + k) * 2;
层层往下写,就发现规律了
D
一道树形dp,有几个需要特判的细节
#include <stdio.h> #include <algorithm> using namespace std; const int N = 1e5+10; int head[N] = {0}, to[N*2], nt[N*2], tot = 0, vis[N] = {0}; void add(int x, int y) { ++tot;nt[tot]=head[x];to[tot]=y;head[x]=tot; ++tot;nt[tot]=head[y];to[tot]=x;head[y]=tot; } int down[N] = {0}, up[N] = {0}; void dfs1(int now, int pre) { // printf("%d --> %d ", pre, now); int maxx[2]; maxx[0] = maxx[1] = 0; for(int i = head[now]; i; i = nt[i]) { if(to[i]==pre) continue; dfs1(to[i], now); if(vis[to[i]]) { down[now] = max(down[now], 1); if(1>maxx[1]) { maxx[0] = maxx[1]; maxx[1] = 1; }else if(1>maxx[0]) { maxx[0] = 1; } } if(down[to[i]]==0) continue; down[now] = max(down[now], down[to[i]] + 1); if(down[to[i]]+1>maxx[1]) { maxx[0] = maxx[1]; maxx[1] = down[to[i]]+1; }else if(down[to[i]]+1>maxx[0]) { maxx[0] = down[to[i]]+1; } } for(int i = head[now]; i; i = nt[i]) { if(to[i]==pre) continue; if(vis[now]) up[to[i]] = max(up[to[i]], 1); if(up[now]) up[to[i]] = max(up[to[i]], up[now] + 1); if((down[to[i]] && down[to[i]]+1==maxx[1]) || (vis[to[i]] && maxx[1]==1)) { // printf(">>%d %d %d %d<< ", now, to[i], maxx[0], maxx[1]); if(maxx[0]) up[to[i]] = max(up[to[i]], maxx[0]+1); } else if(maxx[1]) { up[to[i]] = max(up[to[i]], maxx[1]+1); } // printf("debug : %d - %d ", to[i], up[to[i]]); } } void dfs2(int now, int pre) { for(int i = head[now]; i; i = nt[i]) { if(pre==to[i]) continue; if(up[now]) up[to[i]] = max(up[to[i]], up[now]+1); dfs2(to[i], now); } } int main() { int n, m, d, x, y; scanf("%d %d %d", &n, &m, &d); for(int i = 1; i <= m; i++) { scanf("%d", &x); vis[x] = 1; } for(int i = 1; i < n; i++) { scanf("%d %d", &x, &y); add(x, y); } dfs1(1, 0); // for(int i = 1; i <= n; i++) // { // printf("%d -- %d vs %d ", i, down[i], up[i]); // } // // printf(" "); dfs2(1, 0); // for(int i = 1; i <= n; i++) // { // printf("%d -- %d vs %d ", i, down[i], up[i]); // } int res = 0; for(int i = 1; i <= n; i++) if(up[i]<=d && down[i]<=d) res++; printf("%d ", res); }
E
就是先写一个暴力,然后把自己会的优化都用上,然后这题就过了,说实话,恶心。
自己又因为long long的问题白给了好几发
做完题目,转念一想,确实是自己没有思考完全导致的白给。
这(8!*8*1e6 确实大概率会T)
#include <stdio.h> #include <algorithm> #include <iostream> #include <vector> #include <map> using namespace std; typedef long long ll; ll a[10], rest[10]; int n, res = 1e9, pre[10], tmp, size[10], flag = 0; vector <int> ve[10]; map <ll, ll> mp; int count(ll x) { if(mp[x]) return mp[x]; ll tmp = x; ll res = 0; for(ll i = 2; i * i <= x; i++) { if(x%i==0) { while(x%i==0) { x /= i; res++; } } } if(x>1) res++; return mp[tmp] = res; } bool prime(ll x) { if(x==2 || x==3) return true; for(ll i = 2; i * i <= x; i++) if(x%i==0) return false; return true; } int isprime[10] = {0}; void cal(int now) { tmp++; if(size[now]==0) { if(!isprime[now]) tmp += count(a[now]); return; } if(now) { if(rest[now]) tmp += count(rest[now]); } for(int i = 0; i < size[now]; i++) { cal(ve[now][i]); if(flag) return; } } void dfs(int pos) { if(pos==n+1) { tmp = 0; flag = 0; for(int i = 0; i <= n; i++) { ve[i].clear(); size[i] = 0; } for(int i = 1; i <= n; i++) { size[pre[i]]++; ve[pre[i]].push_back(i); } cal(0); if(size[0]==1) { tmp -= 1; } if(flag) tmp = 1e9; if(tmp < res) { res = tmp; } return ; } for(int i = 0; i < pos; i++) { if(i && rest[i]%a[pos]) continue; rest[i] = rest[i] / a[pos]; pre[pos] = i; dfs(pos+1); rest[i] *= a[pos]; } } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%lld", a+i); sort(a+1, a+n+1, greater<ll>() ); for(int i = 1; i <= n; i++) { rest[i] = a[i]; if(prime(a[i])) isprime[i] = 1; } dfs(1); printf("%d ", res); }