topcoder srm 305 div1
problem1 link
直接按照题意模拟即可。
import java.util.*; import java.math.*; import static java.lang.Math.*; public class UnfairDivision { public int albertsShare(int[] assets) { final int n=assets.length; for(int i=1;i<n;++i) { assets[i]+=assets[i-1]; } int result=0; for(int i=0;i<n-1;++i) { int betty=0,carla=0,albert=0; for(int j=0;j<n-1;++j) { if(j==i) { continue; } int[] a=new int[3]; if(j<i) { a[0]=assets[j]; a[1]=assets[i]-assets[j]; a[2]=assets[n-1]-assets[i]; } else { a[0]=assets[i]; a[1]=assets[j]-assets[i]; a[2]=assets[n-1]-assets[j]; } Arrays.sort(a); if(a[1]>betty||a[1]==betty&&a[2]>carla) { carla=a[2]; betty=a[1]; albert=a[0]; } } result=Math.max(result,albert); } return result; } }
problem2 link
$f[a][b][c][d]$表示将第一个串的$[a,b]$以及第二个串的$[c,d]$拿出来能否拼成一个回文串。每次扩展有四种情况:
(1)第一个串两端相等,那么只需判断$f[a+1][b-1][c][d]$即可;
(2)第一个串的左侧和第二个串右侧相等,只需判断$f[a+1][b][c][d-1]$即可;
(3)第二个串的左侧和第一个串的右侧相等,只需判断$f[a][b-1][c+1][d]$即可;
(4)第二个串左右相等,那么只需判断$f[a][b][c+1][d-1]$即可。
import java.util.*; import java.math.*; import static java.lang.Math.*; public class InterleavePal { final static int INF=99999; int n,m; int[][][][] f=null; String S,T; boolean[][] gs=null; boolean[][] gt=null; boolean check(String s,int ll,int rr) { while(ll<rr) { if(s.charAt(ll)!=s.charAt(rr)) { return false; } ++ll; --rr; } return true; } int dfs(int l1,int r1,int l2,int r2) { if(l1>r1) { if(l2>r2) return 0; if(gt[l2][r2]) return r2-l2+1; return -INF; } if(l2>r2) { if(gs[l1][r1]) return r1-l1+1; return -INF; } if(f[l1][r1][l2][r2]!=-1) { return f[l1][r1][l2][r2]; } int result=-INF; if(l1<r1&&S.charAt(l1)==S.charAt(r1)) { result=Math.max(result,2+dfs(l1+1,r1-1,l2,r2)); } if(S.charAt(l1)==T.charAt(r2)) { result=Math.max(result,2+dfs(l1+1,r1,l2,r2-1)); } if(T.charAt(l2)==S.charAt(r1)) { result=Math.max(result,2+dfs(l1,r1-1,l2+1,r2)); } if(l2<r2&&T.charAt(l2)==T.charAt(r2)) { result=Math.max(result,2+dfs(l1,r1,l2+1,r2-1)); } f[l1][r1][l2][r2]=result; return result; } public int longestPal(String s, String t) { n=s.length(); m=t.length(); if(n==0&&m==0) { return 0; } S=s; T=t; f=new int[n][n][m][m]; int result=0; gs=new boolean[n][n]; for(int i=0;i<n;++i) { for(int j=i;j<n;++j) { if(check(S,i,j)) { gs[i][j]=check(S,i,j); if(gs[i][j]) { result=Math.max(result,j-i+1); } } } } gt=new boolean[m][m]; for(int i=0;i<m;++i) { for(int j=i;j<m;++j) { if(check(T,i,j)) { gt[i][j]=check(T,i,j); if(gt[i][j]) { result=Math.max(result,j-i+1); } } } } if(n==0||m==0) { return result; } for(int i=0;i<n;++i) { for(int j=i;j<n;++j) { for(int k=0;k<m;++k) { for(int p=k;p<m;++p) { f[i][j][k][p]=-1; } } } } for(int i=0;i<n;++i) { for(int j=i;j<n;++j) { for(int k=0;k<m;++k) { for(int p=k;p<m;++p) { result=Math.max(result,dfs(i,j,k,p)); } } } } return result; } }
problem3 link
首先,对于指数是偶数的情况来说,会产生重复,比如$x^{12}=(x^{3})^{4}=(x^{6})^{2}$。因此,只计算指数为素数时可避免这种情况;
其次,$(x^{3})^5=(x^{5})^{3}$。这种情况下,只计算指数较小者。所以在计算到指数为较大的素数时,比如11,假设最大值为$t$,即$t^{11}\leq n,(t+1)^{11}>n$.那么要判断有多少数字$u$满足$u^{k}\leq t$,其中$k<11$。
import java.util.*; import java.math.*; import static java.lang.Math.*; public class PowerCollector { boolean isprime(int k) { for(int i=2;i*i<=k;++i) { if(k%i==0) { return false; } } return true; } long get(long a,int b,long n) { long t=1; for(int i=0;i<b;++i) { if(t>n/a) { return n+1; } t*=a; } return t; } long getMax(long n,int k) { long low=1,high=n; long result=1; while(low<=high) { long M=(low+high)>>1; if(get(M,k,n)>n) { high=M-1; } else { result=Math.max(result,M); low=M+1; } } return result; } long dfs(long n,int k) { long result=1; for(int i=2;i<k;++i) { if(!isprime(i)) { continue; } long t=getMax(n,i); if(t==1) { break; } result+=t-dfs(t,i); } return result; } public String countPowers(String N) { long n=Long.valueOf(N); if(n==1) { return "1"; } return String.valueOf(dfs(n,62)); } }