【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努力搞中……

posted @ 2012-10-03 00:47  Delostik  阅读(462)  评论(0编辑  收藏  举报