Codeforces Round #224 (Div. 2)

B:


if(b>=x) b=b-x

if(b<x)   b=w-(x-b) =>b=b-x+w


其实就是b一直减x,如果小于0了,就加1次w。而且每加一次w必然使b-x+w大于0。

那么就二分过了多少时间t,根据不等式 b-t*x+k*w>0 求出 k。所以a--了k次,也就是c++了k次。

判一下c-t+k<=a。


code:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;

#define N  2013
#define ll long long
#define ALL(x)     x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
#define bit(st,i) ((1ll<<i)&st)
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int MOD   =1000003;
const double EPS=1e-7;


ll a,b,w,x,c;

bool check(ll t){
	ll dif=max(0ll,t*x-b);
	ll d=(dif+w-1)/w;
	return c-t+d<=a;
}

int main(){
	cin>>a>>b>>w>>x>>c;
	ll l=0,r=1ll<<62;
	while(l<r){
		ll mid=(l+r)>>1;
		if(!check(mid)) l=mid+1;
		else r=mid;
	}
	cout<<r<<endl;
	return 0;
}



C: 


分n=1,n=2,n>=3三类讨论清楚即可。


code:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;

#define N  100010
#define ll long long
#define ALL(x)     x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
#define bit(st,i) ((1ll<<i)&st)
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int MOD   =1000003;
const double EPS=1e-7;

int a[N];

int main(){
	int n,d;
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d",&a[i]);
	sort(a,a+n);
	if(n==1) puts("-1");
	else if(n==2){
		if(a[0]!=a[1]){
			d=a[1]-a[0];
			if(d%2==0) puts("3");
			else puts("2");
			printf("%d",a[0]-d);
			if(d%2==0) printf(" %d",a[0]+d/2);
			printf(" %d\n",a[1]+d);
		}else{
			puts("1");
			printf("%d\n",a[0]);
		}
	}else{
		d=a[1]-a[0];
		int x;
		for(int i=1;i<n;i++) d=min(d,a[i]-a[i-1]);
		int cnt=0;
		for(int i=1;i<n;i++) if(a[i]-a[i-1]!=d){
			if(a[i]-a[i-1]==2*d) cnt++,x=a[i-1]+d;
			else{
				puts("0");
				return 0;
			}
		}
		if(cnt>1){
			puts("0");
			return 0;
		}
		if(cnt){
			puts("1");
			printf("%d\n",x);
			return 0;
		}
		if(a[0]-d!=a[n-1]+d){
			puts("2");
			printf("%d %d\n",a[0]-d,a[n-1]+d);
		}else{
			puts("1");
			printf("%d\n",a[0]);
		}
	}
	return 0;
}


D:


显然我们要求出最长路径,记忆化搜索即可。

然后对于最长路径Max,答案至少是2*Max-1(一前一后走最长路径)。除非存在两条最长路径,且某一时刻2个棋子不会碰在一起。判断棋子会不会碰在一起其实很简单。因为每个格子都是单向走的,如果终点一样,那么必然两条路径有重叠的一段。所以搜索的时候再记录下终点即可。


code:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;

#define N  2013
#define ll long long
#define ALL(x)     x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
#define bit(st,i) ((1ll<<i)&st)
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int MOD   =1000003;
const double EPS=1e-7;
const int dx[]  = {-1, 1, 0, 0};
const int dy[]  = {0, 0, -1, 1};

char mp[N][N];
int n,m,dp[N][N],f[N][N];
int sx,sy;

int dir(char c){
	switch(c){
		case '^':return 0;
		case 'v':return 1;
		case '<':return 2;
		case '>':return 3;
	}
}

int dfs(int x,int y){
	if(dp[x][y]!=-1) return dp[x][y];
	dp[x][y]=1;
	f[x][y]=m*x+y;
	int d=dir(mp[x][y]);
	int xx=dx[d]+x;
	int yy=dy[d]+y;
	if(mp[xx][yy]!='#'){
		if(xx==sx && yy==sy){
			puts("-1");
			exit(0);
		}
		if(dp[x][y]<dfs(xx,yy)+1){
			dp[x][y]=dp[xx][yy]+1;
			f[x][y]=f[xx][yy];
		}
	}
	return dp[x][y];
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++) scanf("%s",mp[i]);
	CLR(dp,-1);
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(mp[i][j]!='#' && dp[i][j]==-1){
				sx=i,sy=j;
			   	dfs(i,j);
			}
	int ans=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(mp[i][j]!='#') ans=max(ans,dp[i][j]);
	vector<int> d;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(dp[i][j]==ans) d.push_back(f[i][j]);
	sort(ALL(d));
	d.erase(unique(ALL(d)),d.end());
	ans*=2;
	if(d.size()==1) ans--;
	printf("%d\n",ans);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值