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;
}