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

你可能感兴趣的:(codeforces)