Codeforces #305 Div 1 简要题解
来源:互联网 发布:淘宝红包图片 编辑:程序博客网 时间:2024/04/30 10:54
A. Mike and Frog
题目链接
http://codeforces.com/contest/547/problem/A
题目大意
Xaniar初始的值为
问最少多少秒后,两人的值各变为
思路
tutorial里的神奇做法虽然非常丽洁,但是不太好懂,下面是我想出的另外一种解法
首先我们求出
下面考虑
移项得
这个式子可以通过扩展欧几里得得到一组解
设
对于不定方程
这样我们就能找出一组正整数解
而对于其他情况(如不存在
代码
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>using namespace std;typedef long long int LL;LL MOD,h1,h2,a1,a2,x1,x2,y1,y2;LL t1,t2,t3,t4;LL extGCD(LL a,LL b,LL &x,LL &y){ if(!b) { x=1,y=0; return a; } LL gcd=extGCD(b,a%b,x,y); LL t=x; x=y; y=t-(a/b)*y; //!!! return gcd;}int main(){ scanf("%I64d",&MOD); scanf("%I64d%I64d",&h1,&a1); scanf("%I64d%I64d",&x1,&y1); scanf("%I64d%I64d",&h2,&a2); scanf("%I64d%I64d",&x2,&y2); while(h1!=a1&&t1<MOD+20) { t1++; h1=(h1*x1+y1)%MOD; } if(h1!=a1) { printf("-1\n"); return 0; } while(h2!=a2&&t3<MOD+20) //!!!! { t3++; h2=(h2*x2+y2)%MOD; } if(h2!=a2) { printf("-1\n"); return 0; } if(t1==t3) { printf("%I64d\n",t1); return 0; } while((h1!=a1&&t2<MOD+20)||(h1==a1&&!t2)) { t2++; h1=(h1*x1+y1)%MOD; } while((h2!=a2&&t4<MOD+20)||(h2==a2&&!t4)) { t4++; h2=(h2*x2+y2)%MOD; } if((t1+t2)==(t3+t4)) { printf("%I64d\n",t1+t2); return 0; } if(h1!=a1&&h2==a2) { if(t1>=t3&&(t1-t3)%t4==0) { printf("%I64d\n",t1); return 0; } } if(h2!=a2&&h1==a1) { if(t3>=t1&&(t3-t1)%t2==0) { printf("%I64d\n",t3); return 0; } } if(h1!=a1) { printf("-1\n"); return 0; } if(h2!=a2) { printf("-1\n"); return 0; } LL k,l; LL gcd=extGCD(t2,t4,k,l); LL a=t2/gcd,b=t4/gcd; k=k*(t3-t1)/gcd; //!!! l=l*(t3-t1)/gcd; //!!! if((t3-t1)%gcd) { printf("-1\n"); return 0; } l=-l; if(k<0) { LL tmp=(-k)/b+1; k+=tmp*b; l+=tmp*a; } if(l<0) { LL tmp=(-l)/a+1; k+=tmp*b; l+=tmp*a; } LL ans=k*t2+t1; while(1) { if(l-a>=0&&k-b>=0) { l-=a; k-=b; ans=min(ans,k*t2+t1); } else break; } printf("%I64d\n",ans); return 0;}
B. Mike and Feet
题目链接
http://codeforces.com/contest/547/problem/B
题目大意
对于
思路
首先我们求出两个数组
代码
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#define MAXN 1100000using namespace std;int n,a[MAXN],ans[MAXN];int L[MAXN],R[MAXN];int stack[MAXN],top=0;int main(){ scanf("%d",&n); fill(L,L+MAXN,0); fill(R,R+MAXN,n+1); //!!!! for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) { while(top&&a[stack[top]]>=a[i]) top--; if(top) L[i]=stack[top]; stack[++top]=i; } top=0; for(int i=n;i>=1;i--) { while(top&&a[stack[top]]>=a[i]) top--; if(top) R[i]=stack[top]; stack[++top]=i; } for(int i=1;i<=n;i++) { int len=R[i]-L[i]-1; //!!!! ans[len]=max(ans[len],a[i]); } for(int i=n;i>=1;i--) ans[i]=max(ans[i],ans[i+1]); for(int i=1;i<=n;i++) printf("%d ",ans[i]); printf("\n"); return 0;}
C. Mike and Foam
题目链接
http://codeforces.com/contest/547/problem/C
题目大意
给你
思路
我们可以维护当前的集合
不妨对
这是一个非常简单的容斥,不必过多赘述。因此我们只需要用一个set来维护当前的集合
代码
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#include <set>#define MAXN 510000using namespace std;typedef long long int LL;set<int>bst;set<int>::iterator it;LL ans=0;LL a[MAXN];LL divisors[20];int top=0;LL cnt[1100000]; //cnt[i]=在bst集合里的是数字i的倍数的数字个数LL stack[1<<8];int tot=0; //共有tot种可能的质因数组合乘积void DFS(int pos,int selected,int flag,LL val) //考虑是否选择第pos个质因数,已经选择了selected个质因数,给答案的贡献为flag*xx,要找出是val的倍数的数字个数{ if(pos>top) { if(!selected) return; ans+=cnt[val]*flag; stack[++tot]=val; return; } DFS(pos+1,selected,flag,val); //不选第pos个质因数 DFS(pos+1,selected+1,-flag,val*divisors[pos]); //选第pos个质因数}void modify(LL x,LL flag){ top=tot=0; LL tmp=x; for(LL p=2;p*p<=x;p++) { if(x%p==0) { divisors[++top]=p; while(x%p==0) x/=p; } } if(x&&x!=1) divisors[++top]=x; DFS(1,0,flag,1); //!!!!!}int main(){ int n,q; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%I64d",&a[i]); while(q--) { int x; scanf("%d",&x); //cout<<"size:"<<bst.size()<<endl; if(a[x]==1) { if(bst.count(x)) { bst.erase(x); ans-=bst.size(); printf("%I64d\n",ans); } else { ans+=bst.size(); bst.insert(x); printf("%I64d\n",ans); } } else { if(bst.count(x)) { bst.erase(x); modify(a[x],-1); for(int i=1;i<=tot;i++) cnt[stack[i]]--; ans-=bst.size(); ans--; printf("%I64d\n",ans); } else { ans+=bst.size(); modify(a[x],1); printf("%I64d\n",ans); for(int i=1;i<=tot;i++) cnt[stack[i]]++; bst.insert(x); } } } return 0;}
D. Mike and Fish
题目链接
http://codeforces.com/contest/547/problem/D
题目大意
给你
思路
将每个行标和每个列标均看成是图中的一个结点,对于每个点
显然我们按照行标-列标连边建立的是一个二分图,那么图中奇数度数的点的个数一定是偶数(每次加入一条边,会为所有点的度数和增加2,那么无论如何,所有点的度数和都是偶数,偶数度数点的度数和为偶数,那么奇数度数点的度数和也是偶数,故奇数度数点的个数为偶数),因此我们可以把度数为奇数的点,两两之间依次连无向边,这样每个点的度数就能都变成偶数了。
那么对于每个联通块,我们以一个奇数度数点为起点(若没有,则以偶数度数点为起点),做欧拉回路,显然是存在欧拉回路的,我们对这条路径进行红蓝边交叉染色。
考虑一般情况,之前这个联通块里没有加任何边,则在欧拉回路中,每个点显然出边个数与入边个数相同(即从每个点离开的次数和进入每个点的次数是相同的),而且欧拉回路长度是偶数(无向图
而若之前这个联通块里加了边,则加边后欧拉回路长度依然是偶数,而每个点新连的边最多只有一条,那么每个点连的红边个数和蓝边个数相差一,也满足了题目给出的要求。
代码
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#include <set>#define MAXE 401000#define MAXV 401000using namespace std;int n,degree[MAXV];struct edge{ int v,id; edge(){} edge(int _v,int _id):v(_v),id(_id){}}edges[MAXE*2];bool operator==(edge a,edge b){ return a.v==b.v&&a.id==b.id;}bool operator<(edge a,edge b){ return a.id<b.id;}bool operator>(edge a,edge b){ return a.id>b.id;}set<edge>G[MAXV];int stack[MAXE*2],top=0;bool vis[MAXV];void AddEdge(int U,int V,int ID){ G[U].insert(edge(V,ID)); G[V].insert(edge(U,ID));}void DFS(int u){ vis[u]=true; while(!G[u].empty()) { int v=G[u].begin()->v; int id=G[u].begin()->id; G[u].erase(edge(v,id)); G[v].erase(edge(u,id)); DFS(v); stack[++top]=id; }}int oddpoints[MAXV],tot=0;char ans[MAXV];int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); y+=200000; //!!!!! degree[x]++,degree[y]++; AddEdge(x,y,i); AddEdge(y,x,i); } for(int i=1;i<=400000;i++) if(degree[i]&1) oddpoints[++tot]=i; for(int i=1;i<=tot;i+=2) { AddEdge(oddpoints[i],oddpoints[i+1],0); AddEdge(oddpoints[i+1],oddpoints[i],0); } for(int i=1;i<=tot;i++) { if(vis[oddpoints[i]]) continue; DFS(oddpoints[i]); bool flag=false; while(top) { flag^=1; if(stack[top]) ans[stack[top]]=flag?'r':'b'; top--; } } for(int i=1;i<=400000;i++) { if(vis[i]) continue; DFS(i); bool flag=false; while(top) { flag^=1; if(stack[top]) ans[stack[top]]=flag?'r':'b'; top--; } } printf("%s\n",ans+1); return 0;}
- Codeforces #305 Div 1 简要题解
- [Codeforces #295(Div 1)]简要题解
- Codeforces #299 Div 1 简要题解
- Codeforces #292 Div 1 简要题解
- Codeforces #290 Div. 1 简要题解
- Codeforces #286 Div 1 简要题解
- Codeforces #285 Div 1 简要题解
- Codeforces #284 Div 1 简要题解
- Codeforces #283 Div 1 简要题解
- Codeforces #278 Div 1 简要题解
- Codeforces #275 Div 1 简要题解
- Codeforces #274 Div 1 简要题解
- Codeforces #272 Div 1 简要题解
- Codeforces #268 Div 1 简要题解
- Codeforces #265 Div 1 简要题解
- Codeforces #263 Div 1 简要题解
- Codeforces #310 Div 1 简要题解
- Codeforces #309 Div 1 简要题解
- 【转】iOS开发学习计划
- Ajax get解决跨域问题(只能用get方法)
- IOS开发常用数学函数
- STL 中map 和 set 的知识点总结
- 3.7WildcardMatching
- Codeforces #305 Div 1 简要题解
- android-support-v13编译错误解决
- Androrat 编译运行错误集
- [ACM]常用工具函数整理
- OpenCL编程步骤(四):创建内核对象和设置内核参数
- 软件工程之数据流图
- 总结几个C语言中的“坑”(一)
- Android GridView子元素item按击交互设计:背景颜色改变
- win8 上安装SVN时出现2503错误解决方法