【Codeforces #142 Div2】Solutions
先发Div2的吧,Div1的要看能搞定多少……(一般不全搞出来是不会写题解的……)
【A. Dragons】
http://www.codeforces.com/contest/230/problem/A
题目大意:有个人打怪兽,自己和怪兽都有一个属性,属性高的能战胜低的,打败一个怪兽能获得额外属性。问能否全胜通关。
从小到大打就是了……没什么意思……
#include <iostream> #include <algorithm> using namespace std; int s,n; struct REC{int x,y;}a[1010]; bool cmp(REC a,REC b){ return a.x<b.x; } int main(){ cin>>s>>n; for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y; sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++){ if(s<=a[i].x){ cout<<"NO"<<endl; return 0; } s+=a[i].y; } cout<<"YES"<<endl; }
【B. T-primes】
http://www.codeforces.com/contest/230/problem/B
题目大意:给定一堆数,判断他们每个是不是T-prime,T-prime数定义为该数有且仅有三个质因子。
任何一个数都有1和它本身俩质因子。还剩一个……是啥呢?只有sqrt(n)。因为如果不是它的话,必然会产生偶数个质因子。
比较坑人,也没什么意思……
#include <iostream> #include <cmath> #define sqr(x) ((x)*(x)) using namespace std; bool composite[1000010]; int n; long long x; int main(){ composite[1]=true; for(int i=2;i<=1000000;i++) if(!composite[i]){ for(int j=2;i*j<=1000000;j++) composite[i*j]=true; } cin>>n; while(n--){ cin>>x; if(sqr((long long)sqrt(x))!=x) cout<<"NO"<<endl; else if(composite[(int)sqrt(x)]) cout<<"NO"<<endl; else cout<<"YES"<<endl; } }
【C. Shifts】
http://www.codeforces.com/contest/230/problem/C
做div1的时候这个题挂了,很囧……
题目大意:给一个01矩阵,行可以转(密码锁那样),问最少转几次出现一列全是1.
mov[i][j]表示使第i行第j列出现1的最少移动次数。循环的数组显然要拆分一下,然后正着倒着各一边dp,最后枚举列统计一下就ok了……
#include <iostream> #include <cstring> using namespace std; template<class T>inline void gmin(T &a,T b){if(a>b)a=b;} char s[10010]; int n,m,ans=2147483647,mov[110][10010],tmp; int main(){ cin>>n>>m; for(int i=1;i<=n;i++) for(int j=0;j<m;j++) mov[i][j]=1000000; for(int i=1;i<=n;i++){ cin>>s; for(int j=0;j<m;j++) if(s[j]=='1') mov[i][j]=0; for(int j=0;j<m<<1;j++) gmin(mov[i][j%m],mov[i][(j-1+m)%m]+1); for(int j=(m<<1)-1;j>=0;j--) gmin(mov[i][j%m],mov[i][(j+1)%m]+1); } for(int j=0;j<m;j++){ tmp=0; for(int i=1;i<=n;i++) tmp+=mov[i][j]; gmin(ans,tmp); } cout<<(ans>=1000000?-1:ans)<<endl; }
【D. Planets】
http://www.codeforces.com/contest/230/problem/D
题目大意:无向图从1走到n,某些特殊时间某些特殊点不能出发,问最短时间。
大概算法就是最短路就行(比如SPFA),复杂度瓶颈在于如何知道某一点某一时刻能不能走,可以对于每个点建一个查找树,就过了。C++用map或者set都行。
#include <iostream> #include <cstring> #include <queue> #include <map> #define mn 100010 #define mm 200010 using namespace std; map<int,bool> bst[mn]; queue<int> q; int n,m,a,b,c,dist[mn]; bool vis[mn]; struct EDGE{ int pnt,dist; EDGE *pre; EDGE(){} EDGE(int _pnt,int _dist,EDGE *_pre):pnt(_pnt),pre(_pre),dist(_dist){} }Edge[mm],*SP=Edge,*edge[mn]; inline void addedge(int a,int b,int c){ edge[a]=new(++SP)EDGE(b,c,edge[a]); edge[b]=new(++SP)EDGE(a,c,edge[b]); } int main(){ cin>>n>>m; while(m--){ cin>>a>>b>>c; addedge(a,b,c); } for(int i=1;i<=n;i++){ cin>>a; while(a--){ cin>>b; bst[i][b]=true; } } memset(dist,0x7f,sizeof(dist)); dist[1]=0; q.push(1); while(!q.empty()){ int i=q.front();q.pop(); vis[i]=false; int cur_time=dist[i]; while(bst[i][cur_time]) cur_time++; for(EDGE *j=edge[i];j;j=j->pre) if(j->dist+cur_time<dist[j->pnt]){ dist[j->pnt]=cur_time+j->dist; if(!vis[j->pnt]){ vis[j->pnt]=true; q.push(j->pnt); } } } cout<<(dist[n]==dist[0]?-1:dist[n])<<endl; }
【E. Triangles】
http://www.codeforces.com/contest/230/problem/E
题目大意:一个完全图,拆成两部分,问这两部分一共有多少三角形。
完全图中共有C(n,3)个三角形,对于某个点x,如果有deg[x]个点与x相连,那么剩下(n-x-1)个点就不与x相连了,于是就减少了deg[x]*(n-deg[x]-1)个包含x的三角形(乘法原理)。最后处理一下重复统计。
#include <cstdio> int m,a,b,deg[1000010]; long long n,tri; int main(){ scanf("%I64d%d",&n,&m); while(m--){ scanf("%d%d",&a,&b); deg[a]++,deg[b]++; } for(int i=1;i<=n;i++) tri+=(long long)deg[i]*(n-deg[i]-1); tri>>=1; printf("%I64d\n",n*(n-1)*(n-2)/6-tri); }
Div1努力搞中……