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