topcoder srm 445 div1

problem1 link

这个的结论是只需要考虑坐标是整数或者是整数.5,比如(2.5,3),(4,3.5),(1.5,4.5)这样的时候。这个详细证明起来应该挺麻烦的。这里有一些讨论。

problem2 link

首先,可以暴力看下$n=3,4$时的情况。

$n=3$,

000

001

011

010

110

100

101

111

$n=4$,

0000

0001

0011

0010

0110

0100

0101

0111

1111

1000

1001

1011

1010

1110

1100

1101

这时候可以发现,规律是最高位从0变到1的时候,后面的位数进行了一次shift。

而题目是求最大值,即getMax(n,k)。

(1)当$k\leq 2^{n-1}$时,getMax(n,k)="0"+getMax(n-1,k)

(2)当$k=1+ 2^{n-1}$时,getMax(n,k)="1"+get(n-1,$2^{n-1}$)

(3)当$k>1+ 2^{n-1}$时,getMax(n,k)="1"+max(get(n-1,$2^{n-1}$),getMax(n-1,k-m-1))

其中,get(n,k)表示得到长度为$n$的第$k$个串。

 

problem3 link

可以把问题转化为可以构造多少种不同的长度为52的(msg,encMsg)二元对(只是msg中是已经排序的)。现在$msg$中的某些位置已经确定。只需要考虑那些未确定的即可。

每次可以选择一个在原串中未确定的最小(防止重复)的,枚举它匹配加密串中未确定的每一个可合法匹配的。

另外,在原串中,一个字符可能使用了0次、1次、2次,也就是还可以使用2次、1次、0次,同样一个字符在加密串中还可以使用2次、1次、0次。所以搭配一下有3*3=9种情况,(x,y)表示在原串中还可以使用$x$次,在加密串中还可以使用$y$次的的字符种类数

那么每次需要从(2,*),(1,*)中选择一个匹配(*,1)或者(*,2)中的一个。


code for problem1

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

public class TheNewHouseDivOne {
	
	public double distance(int[] x, int[] y, int k) {
		double min=1e10;
		double[] a=new double[x.length];
		for(int i=0;i<=200;++i) {
			for(int j=0;j<=200;++j) {
				final double xx=-50+i*0.5;
				final double yy=-50+j*0.5;
				for(int t=0;t<x.length;++t) {
					a[t]=Math.abs(xx-x[t])+Math.abs(yy-y[t]);
				}
				Arrays.sort(a);
				if(a[k-1]<min) {
					min=a[k-1];
				}
			}
		}
		return min;
	}
}

  

code for problem2

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

public class TheLockDivOne {

	public String password(int n, long k) {
		return getMax(n,k);
	}

	String getMax(int n,long k) {
		if(n==1) {
			return k==1?"0":"1";
		}
		long m=1l<<(n-1);
		if(k<=m) {
			return "0"+getMax(n-1,k);
		}
		else if(k==m+1) {
			return "1"+get(n-1,m);
		}
		else {
			String a=get(n-1,m);
			String b=getMax(n-1,k-m-1);
			if(a.compareTo(b)<0) {
				return "1"+b;
			}
			return "1"+a;
		}
	}

	String get(int n,long k) {
		if(n==1) {
			return k==1?"0":"1";
		}
		long m=1l<<(n-1);
		if(k<=m) {
			return "0"+get(n-1,k);
		}
		else if(k==m+1) {
			return "1"+get(n-1,m);
		}
		else {
			return "1"+get(n-1,k-m-1);
		}
	}
}

 

code for problem3

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

public class TheEncryptionDivOne {

	static final int MOD=1234567891;

	Map<Long,Integer> map=new HashMap<>();

	public int count(String msg, String encMsg) {
		int[] p=new int[52];
		int[] q=new int[52];
		Arrays.fill(p,-1);
		Arrays.fill(q,-1);
		for(int i=0;i<msg.length();++i) {
			int u=get(msg.charAt(i));
			int v=get(encMsg.charAt(i));
			if(u%26==v%26) {
				return 0;
			}
			if(p[u]!=-1&&p[u]!=v||q[v]!=-1&&q[v]!=u) {
				return 0;
			}
			p[u]=v;
			q[v]=u;
		}
		int[][] c=new int[3][3];
		for(int i=0;i<26;++i) {
			int x=0,y=0;
			if(p[i]==-1) {
				++x;
			}
			if(p[i+26]==-1) {
				++x;
			}
			if(q[i]==-1) {
				++y;
			}
			if(q[i+26]==-1) {
				++y;
			}
			++c[x][y];
		}
		return dfs(c);
	}

	int dfs(int[][] c){
		final long h=hash(c);
		if(map.containsKey(h)) {
			return map.get(h);
		}
		int c1=-1,c2=0;
		for(int i=2;i>=1&&c1==-1;--i) {
			for(int j=2;j>=0;--j) {
				if(c[i][j]>0) {
					c1=i;
					c2=j;
					break;
				}
			}
		}

		if(c1==-1) {
			map.put(h,1);
			return 1;
		}

		int result=0;
		for(int i=2;i>=0;--i) {
			for(int j=2;j>=1;--j) {
				if(c[i][j]==0) {
					continue;
				}
				long num=c[i][j]*j;
				if(i==c1&&j==c2) {
					num-=j;
				}
				if(num<=0) {
					continue;
				}
				--c[i][j];
				--c[c1][c2];
				++c[i][j-1];
				++c[c1-1][c2];
				result=(int)((result+dfs(c)*num)%MOD);
				++c[i][j];
				++c[c1][c2];
				--c[i][j-1];
				--c[c1-1][c2];
			}
		}

		map.put(h,result);
		return result;
	}

	int get(char c) {
		if(c>='A'&&c<='Z') {
			return c-'A';
		}
		return c-'a'+26;
	}
	long hash(int[][] c) {
		long ans=0;
		for(int i=0;i<3;++i) {
			for(int j=0;j<3;++j) {
				ans=(ans<<5)|c[i][j];
			}
		}
		return ans;
	}
}

  

posted @ 2017-10-14 12:31  朝拜明天19891101  阅读(205)  评论(0编辑  收藏  举报