Codeforces Bubble Cup 8 - Finals [Online Mirror] 解题报告
来源:互联网 发布:java开发物流管理系统 编辑:程序博客网 时间:2024/05/17 04:29
D Tablecity
从一头往另一头扫一遍,再逆着回来就好了。因为贼每走一步,横坐标的奇偶性都会改变。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int i;int main(){printf("2000\n");for (i=1;i<=1000;i++) printf("%d 1 %d 2\n",i,i);for (i=1000;i>0;i--) printf("%d 1 %d 2\n",i,i);return 0;}
H Bots
每走一步,树增加了一层,节点数是上一层的2倍。但是到了第n+1层开始,就会出现红/蓝边数量达到n的情况,这样的节点不能翻倍,计算一下组合数把这种情况减去就行了。算组合数的时候递推计算,用到了逆元。
#include <iostream> #include <cstdio> #include <algorithm> #include <set>#include <vector>#include <string.h>using namespace std; #define ll long longconst int mod=1000000007;void ExEuclid(ll a,ll b,ll &x,ll &y,ll &q){ if(b==0){ x=1;y=0;q=a; return; } ExEuclid(b,a%b,y,x,q); y-=x*(a/b); } ll inv(ll num){ ll x,y,q; ExEuclid(num,mod,x,y,q); if(q==1)return (x+mod)%mod; } int main(){int n;while(cin>>n){ll ans=1;ll cur=1;ll C=1;for(int i=1;i<=n*2;i++){cur*=2;cur%=mod;if(i>n){cur-=2*C;cur+=mod;cur+=mod;cur%=mod;C*=i;C%=mod;C*=inv(i-n);C%=mod;}ans+=cur;ans%=mod;}cout<<ans<<endl;}return 0;}
F Bulbo
首先有一个可以推出来的结论,你只移动到输入数据中出现的那些位置,可以得到最优解(不需要移动到数据中没有出现的位置去)。所以就可以用离散化+dp+滚动数组来解决了。dp(i,j)表示第i轮时,位置在j(离散化后)的最优解(第一维滚动只开2)。注意状态转移时,本应是多个状态转移到一个状态,这样复杂度太高会超时,需要利用递推维护多个状态的最优值,一次性转移到一个状态。
顺便说一下,后来发现这个题可以贪心,每次维护一个范围,每次开始前移动到这个范围内,灯亮,花费为最少。
#include <iostream> #include <cstdio> #include <algorithm> #include <set>#include <vector>#include <string.h>using namespace std; #define ll long longconst int mod=1000000007;ll INF=1000000000000000000LL;int l[5010];int r[5010];ll dp[2][100010];int pos[100010];int k;int main(){int n,x;while(cin>>n>>x){memset(dp,-1,sizeof(dp));ll ans=INF;k=0;pos[k++]=x;for(int i=1;i<=n;i++){scanf("%d%d",&l[i],&r[i]);pos[k++]=l[i];pos[k++]=r[i];}sort(pos,pos+k);k=unique(pos,pos+k)-pos;for(int i=0;i<k;i++){dp[0][i]=abs(x-pos[i]);}for(int i=1;i<=n;i++){ll part2=INF;for(int j=0;j<k;j++){dp[i%2][j]=INF;ll part1=0;if(pos[j]<l[i]){part1=l[i]-pos[j];}else if(pos[j]>r[i]){part1=pos[j]-r[i];}if(j>0){part2=min(part2+pos[j]-pos[j-1],dp[(i-1)%2][j]);}else{part2=dp[(i-1)%2][j];}dp[i%2][j]=min(dp[i%2][j],part1+part2);}part2=INF;for(int j=k-1;j>=0;j--){ll part1=0;if(pos[j]<l[i]){part1=l[i]-pos[j];}else if(pos[j]>r[i]){part1=pos[j]-r[i];}if(j<k-1){part2=min(part2+pos[j+1]-pos[j],dp[(i-1)%2][j]);}else{part2=dp[(i-1)%2][j];}dp[i%2][j]=min(dp[i%2][j],part1+part2);}}for(int i=0;i<k;i++){ans=min(ans,dp[n%2][i]);}cout<<ans<<endl;}return 0;}
B Bribes
首先为了迅速求得树上许多点对之间的距离,需要使用nlogn的在线LCA(倍增法)。然后需要知道每条单向边被逆行了多少次,这时可用打标记的方法,起点+1终点-1,又由于它是树型结构,统计时用dfs。最后的计算利用了等比数列求和公式和快速幂。
#include <iostream> #include <cstdio> #include <algorithm> #include <set>#include <vector>#include <string.h>using namespace std; #define ll long longconst int mod=1000000007;ll INF=1000000000000000000LL;#define max_size 100010 ll Quick_Pow(ll a,ll n){ ll ret=1; ll temp=a%mod; while (n){ if (n&1) ret=ret*temp%mod; temp=temp*temp%mod; n>>=1; } return ret; } int d[max_size],p[max_size][18]; int head[max_size]; int cnt;int a[max_size];int b[max_size];int x[max_size];bool downpoint[max_size];bool uppoint[max_size];int downres[max_size];int upres[max_size];bool vis2[max_size];struct Edge{ int v; int pre; }eg[max_size]; void add(int x,int y){ eg[cnt].v=y; eg[cnt].pre=head[x]; head[x]=cnt++; } void dfs(int k){ int m,x,i,j; for(i=head[k];i!=0;i=eg[i].pre){ x=eg[i].v; p[x][0]=k; m=k; d[x]=d[k]+1; for(j=0;p[m][j]!=0;j++){ p[x][j+1]=p[m][j]; m=p[m][j]; } dfs(x); } } int find_lca(int x,int y){ int m,k; if(x==y)return x; if(d[x]<d[y]){ m=x; x=y; y=m; } m=d[x]-d[y]; k=0; while(m){ if(m&1) x=p[x][k]; m>>=1; k++; } if(x==y)return x; k=0; while(x!=y){ if(p[x][k]!=p[y][k]||p[x][k]==p[y][k]&&k==0){ x=p[x][k]; y=p[y][k]; k++; } else{ k--; } } return x; }struct oriEdge{ int v; int flag; oriEdge(int v,int flag):v(v),flag(flag){ } oriEdge(){ }};vector<oriEdge> E[max_size]; bool vis[max_size]; int siz[max_size]; int predfs(int u){ vis[u]=1; int sz=E[u].size(); siz[u]=1; for(int i=0;i<sz;i++){ int v=E[u][i].v; if(!vis[v]){ if(E[u][i].flag==0){ downpoint[v]=1; } if(E[u][i].flag==1){ uppoint[v]=1; } add(u,v); siz[u]+=predfs(v); } } return siz[u]; } ll ans=0;int downcnt[max_size];int upcnt[max_size];void dfs2(int k){downcnt[k]+=downres[k]; upcnt[k]+=upres[k]; for(int i=head[k];i!=0;i=eg[i].pre){ int x=eg[i].v; dfs2(x); downcnt[k]+=downcnt[x]; upcnt[k]+=upcnt[x]; } if(uppoint[k]){ans+=Quick_Pow(2,upcnt[k])-1;ans+=mod;ans%=mod;}if(downpoint[k]){ans+=Quick_Pow(2,downcnt[k])-1;ans+=mod;ans%=mod;}} int main(){ int n; while(cin>>n){ cnt=1; for(int i=1;i<n;i++){ scanf("%d%d%d",&a[i],&b[i],&x[i]); if(!x[i])E[a[i]].push_back(oriEdge(b[i],2)); else E[a[i]].push_back(oriEdge(b[i],1)); if(!x[i])E[b[i]].push_back(oriEdge(a[i],2)); else E[b[i]].push_back(oriEdge(a[i],0)); } predfs(1); dfs(1); int k; cin>>k; int Last=1; for(int i=1;i<=k;i++){ int s; scanf("%d",&s); int LCA=find_lca(Last,s); ll cur=0; if(Last!=LCA){ upres[Last]++; upres[LCA]--; } if(s!=LCA){ downres[s]++; downres[LCA]--; } Last=s; } dfs2(1); cout<<ans<<endl; } return 0;}
G Run for beer
注意题目给的数据范围,边的长度最长是9,但是每多经过一个点,速度变为1/10。也就是说,需要经过尽可能少的点。另外,边长度可以是0,也就是说,如果最后经过了一系列长度为0的边,是不会增加时间的。我的做法是多次bfs,先找出哪些点到终点可以全是0边,然后在这些点中,找一个离起点最近的,再贪心找到路径。实现比较挫,bfs了好多次,也跪了好多次,最后才过。。。
#include <iostream> #include <cstdio> #include <algorithm> #include <set>#include <stack>#include <vector>#include <queue>#include <string.h>using namespace std; #define ll long longconst int INF = 1000000000;const int maxm=100010;const int maxn=100010;int head[maxn];int pre[maxm<<1];int from[maxm<<1];int to[maxm<<1];int len[maxm<<1];int vis[maxn];int tote;int k;int lv[maxn];int _lv[maxn];bool finish[maxn];bool finish2[maxn];int cost[maxn];int lvcost[maxn];int fa[maxn];int _fa[maxn];void init(){memset(head,-1,sizeof(head));tote=0;k=0;}void addedge(int u,int v,int l){to[tote]=v;from[tote]=u;len[tote]=l;pre[tote]=head[u];head[u]=tote++;//to[tote]=u;from[tote]=v;len[tote]=l;pre[tote]=head[v];head[v]=tote++;}int ans[maxn];int path[maxn];void clearQueue(queue<int> &que){while(que.size())que.pop();}int print(int u){int re=0;if(!finish[u])printf("%d",cost[u]);if(u)re=print(from[fa[u]])+1;path[k++]=u;return re;}int main(){init();int n,m;cin>>n>>m;for(int i=1;i<=m;i++){int u,v,l;scanf("%d%d%d",&u,&v,&l);addedge(u,v,l);}queue<int> que;que.push(0);vis[0]=1;while(que.size()){int u=que.front();que.pop();for(int i=head[u];~i;i=pre[i]){int v=to[i];if(vis[v])continue;vis[v]=1;lv[v]=lv[u]+1;que.push(v);}}clearQueue(que);memset(vis,0,sizeof(vis));que.push(n-1);vis[n-1]=1;while(que.size()){int u=que.front();que.pop();finish[u]=1;for(int i=head[u];~i;i=pre[i]){int v=to[i];if(len[i])continue;//only 0 edgeif(vis[v])continue;vis[v]=1;_lv[v]=_lv[u]+1;que.push(v);_fa[v]=i;}}int MIN=INF;for(int i=0;i<n;i++){if(finish[i]){MIN=min(MIN,lv[i]);}}for(int i=0;i<n;i++){if(lv[i]!=MIN){finish[i]=0;}}clearQueue(que);memset(vis,0,sizeof(vis));for(int i=0;i<n;i++){lvcost[i]=INF;if(finish[i]){que.push(i);vis[i]=1;}else{cost[i]=INF;}}lvcost[MIN]=0;while(que.size()){int u = que.front();que.pop();if(lvcost[lv[u]]!=cost[u])continue;for(int i=head[u];~i;i=pre[i]){int v=to[i];if(lv[v]+1!=lv[u])continue;cost[v]=min(cost[v],len[i]);lvcost[lv[v]]=min(lvcost[lv[v]],cost[v]);if(vis[v])continue;vis[v]=1;que.push(v);}}clearQueue(que);memset(vis,0,sizeof(vis));que.push(0);vis[0]=1;while(que.size()){int u=que.front();que.pop();if(finish[u]){finish2[u]=1;}for(int i=head[u];~i;i=pre[i]){if(len[i]!=cost[u])continue;int v=to[i];if(vis[v])continue;vis[v]=1;que.push(v);fa[v]=i;}}int MIN2=INF;int target=-1;for(int i=0;i<n;i++){if(finish2[i]){if(_lv[i]<MIN2){MIN2=_lv[i];target=i;}}}if(print(target)==0){printf("0");}printf("\n");int cur=target;if(cur!=n-1)while(1){cur=from[_fa[cur]];path[k++]=cur;if(cur==n-1)break;}cout<<k<<endl;for(int i=0;i<k;i++){printf("%d ",path[i]);}return 0;}
- Codeforces Bubble Cup 8 - Finals [Online Mirror] 解题报告
- Bubble Cup 8 - Finals [Online Mirror]
- Bubble Cup 8 - Finals [Online Mirror]C. Party
- Bubble Cup 9 - Finals [Online Mirror] 题解
- Bubble Cup 8 - Finals [Online Mirror] - A.Fibonotci【分段+ST表】
- Bubble Cup 9 - Finals [Online Mirror] C. Potions Homework (水题)
- 图论+DFS——Bubble Cup 9 - Finals [Online Mirror] E
- VK Cup 2015 - Finals, online mirror
- Codeforce Bubble Cup 8 - Finals D Tablecity
- codeforces ABBYY Cup 3.0 - Finals (online version) B2. Shave Beaver!
- codeforce Bubble Cup 8 - Finals G Run for beer
- VK Cup 2015 - Finals, online mirror F. Clique in the Divisibility Graph 数论
- VK Cup 2015 - Finals, online mirror D. Restructuring Company 并查集 stl应用
- VK Cup 2015 - Finals, online mirror F - Clique in the Divisibility Graph dp
- Matching Names(Trie树)-(VK Cup 2015 - Finals, online mirror)
- VK Cup 2015 - Finals, online mirror D. Restructuring Company 并查集 set 二分
- Bubble Cup 9 - Finals E. 搜索
- [排序不等式] Codeforces 717C Bubble Cup 9 - Finals C. Potions Homework
- wxpython初学者(三) 之flexgirdsizer,TextEntryDialog,SingleChoiceDialog
- ContentValues、HashTable、HashMap异同
- 新浪微博自定制TabBar
- 剑指Offer系列---(7)从尾到头打印链表
- Linux系统分区
- Codeforces Bubble Cup 8 - Finals [Online Mirror] 解题报告
- 打开Dreamweaver出现配置错误的解决方法
- JVM运行时数据区域
- sting的方法总结
- 控制GridView中的行高
- Merge sort
- Android五大存储---外部存储(SD卡)
- SQL-----sql
- nginx集群的配置