topcoder srm 300 div1

problem1 link

直接模拟即可。

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class Dating {

	static boolean sametype(char c1,char c2) {
		return 'a'<=c1&&c1<='z'&&'a'<=c2&&c2<='z'
				||'A'<=c1&&c1<='Z'&&'A'<=c2&&c2<='Z';
	}
	
	public String dates(String circle, int k) {
		StringBuilder builder=new StringBuilder();
		int startIndex=0;
		while(true) {
			boolean lower=false;
			boolean upper=false;
			for(int i=0;i<circle.length();++i) {
				char c=circle.charAt(i);
				if('a'<=c&&c<='z') {
					lower=true;
				}
				else {
					upper=true;
				}
				if(lower&&upper) {
					break;
				}
			}
			if(!lower||!upper) {
				break;
			}
			for(int i=0;i<k-1;++i) {
				++startIndex;
				if(startIndex==circle.length()) {
					startIndex=0;
				}
			}
			int chooseIndex=-1;
			for(int i=0;i<circle.length();++i) {
				if(i==startIndex) {
					continue;
				}
				char c1=circle.charAt(i);
				char c2=circle.charAt(startIndex);
				if(!sametype(c1,c2)) {
					if(chooseIndex==-1||circle.charAt(chooseIndex)>c1) {
						chooseIndex=i;
					}
				}
			}
			if(builder.length()>0) {
				builder.append(" ");
			}
			builder.append(circle.charAt(startIndex)).append(circle.charAt(chooseIndex));
			if(chooseIndex<startIndex) {
				circle=circle.substring(0,chooseIndex)+
						circle.substring(chooseIndex+1,startIndex)+
						circle.substring(startIndex+1);
				startIndex-=1;
				if(startIndex==circle.length()) {
					startIndex=0;
				}
			}
			else {
				circle=circle.substring(0,startIndex)+
						circle.substring(startIndex+1,chooseIndex)+
						circle.substring(chooseIndex+1);
				if(startIndex==circle.length()) {
					startIndex=0;
				}
			}
		}
		return builder.toString();
	}
}

problem2 link

设$h(x)$表示$[1,x]$范围内有多少符合要求的数字,那么题意就是计算$h(high)-h(low-1)$。

对于$h(n)$来说,设$n$有$d$位数字,$f(x)(y)(z)$表示已经考虑的数字的高$x$位,$y$表示已经考虑的数字中跟$n$的高$x$位相等还是小于还是已经考虑的高$x$位都是0,三种情况;$y$表示前一位数字是多少。

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class JumpyNum {

	int[][][] f=null;
	int[] digit=null;

	int dfs(int d,int tag,int pre) {
		if(d<0) {
			return tag==2?0:1;
		}
		if(f[d][tag][pre]!=-1) {
			return f[d][tag][pre];
		}
		int result=0;
		for(int i=0;i<10;++i) {
			if(tag==0) {
				if(Math.abs(i-pre)>=2) {
					result+=dfs(d-1,0,i);
				}
			}
			else if(tag==1) {
				if(i<=digit[d]&&Math.abs(i-pre)>=2) {
					result+=dfs(d-1,i==digit[d]?1:0,i);
				}
			}
			else {
				result+=dfs(d-1,i==0?2:0,i);
			}
		}
		return f[d][tag][pre]=result;
	}

	int cal(int n) {
		if(n<10) {
			return n;
		}
		int d=String.valueOf(n).length();
		digit=new int[d];
		for(int i=0;i<d;++i) {
			digit[i]=n%10;
			n/=10;
		}
		f=new int[d][3][10];
		for(int i=0;i<d;++i) {
			for(int j=0;j<3;++j) {
				for(int k=0;k<10;++k) {
					f[i][j][k]=-1;
				}
			}
		}
		int result=0;
		for(int i=0;i<=digit[d-1];++i) {
			if(i==0) {
				result+=dfs(d-2,2,0);
			}
			else {
				result+=dfs(d-2,i==digit[d-1]?1:0,i);
			}
		}
		return result;
	}
	
	public int howMany(int low, int high) {
		return cal(high)-cal(low-1);
	}
}

 

problem3 link

首先求出与$x$轴的所有交点,然后每两个相邻交点的中间的范围都有可能被绕过若干圈(如果它不在外部或者边上)。这时可以取中间值进行计算。

对于某个点,将其与每条边的两个端点连线,计算转过的角度即可。如果在外部,那么转过的总角度是0,在内部一定是$2pi$的若干倍。

对于两个向量$vec{a},vec{b}$,可以用$arctan(t)$来计算转角,其中$t=frac{cross(vec{a},vec{b})}{dot(vec{a},vec{b})}$。因为$frac{dot(vec{a},vec{b})}{|vec{a}|}$表示$vec{b}$在$vec{a}$上的投影长度,$frac{cross(vec{a},vec{b})}{|vec{a}|}$表示以$vec{a},vec{b}$为边的平行四边形的高(面积除以底边长),所以它们的比值就是转角的正切值。

import java.util.*;
import java.math.*;
import static java.lang.Math.*;


class point
{
	public double x;
	public double y;

	public point(){}
	public point(double x,double y) {
		this.x=x;
		this.y=y;
	}

	public double crossMultiply(point a)
	{
		return x*a.y-y*a.x;
	}

	public point substract(point a)
	{
		return new point(x-a.x,y-a.y);
	}

	public double dotMultiply(point a)
	{
		return x*a.x+y*a.y;
	}

	public double calculateAngle(point a)
	{
		return Math.atan2(crossMultiply(a),dotMultiply(a));
	}

	public void print()
	{
		System.out.println("x="+x+", y="+y);
	}
};

public class AllWoundUp {

	static int cal(double t,int[] px,int[] py) {
		double sum=0;
		final int n=px.length;
		for(int i=0;i<n;++i) {
			int x0=px[i],y0=py[i];
			int x1=px[(i+1) % n],y1=py[(i+1)%n];
			if(y0==y1&&y0==0) {
				continue;
			}
			sum+=new point(x0-t,y0).calculateAngle(new point(x1-t,y1));
		}
		return (int)(sum/2/Math.PI+0.5);

	}
	
	public int maxWind(int[] x, int[] y) {



		List<Double> list=new ArrayList<>();
		final int n=x.length;
		for(int i=0;i<n;++i) {
			int x0=x[i],y0=y[i];
			int x1=x[(i+1)%n],y1=y[(i+1)%n];
			if(y0==y1) {
				continue;
			}
			if(x0==x1) {
				if(y0*y1<=0) {
					list.add((double)x0);
				}
				continue;
			}
			if(y0*y1>0) {
				continue;
			}
			double k=1.0*(y0-y1)/(x0-x1);
			list.add(-y0/k+x0);
		}
		Collections.sort(list);
		int result=0;
		for(int i=1;i<list.size();++i) {
			if(Math.abs(list.get(i)-list.get(i-1))<1e-10) {
				continue;
			}
			double t=(list.get(i)+list.get(i-1))/2;
			boolean tag=false;
			for(int j=0;j<n;++j) {
				int x0=x[j],y0=y[j];
				int x1=x[(j+1)%n],y1=y[(j+1)%n];
				if(y0==y1&&y0==0&&Math.min(x0,x1)<=t&&t<=Math.max(x0,x1)) {
					tag=true;
					break;
				}
			}
			if(tag) {
				continue;
			}
			result=Math.max(result,cal(t,x,y));
		}
		return result;
	}
}

  

原文地址:https://www.cnblogs.com/jianglangcaijin/p/7353671.html