problem1 link
直接模拟。
import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class Arrows { public int longestArrow(String s) {
int result=-1;
for(int i=0;i<s.length();++i) {
final char c=s.charAt(i);
if(c=='<') {
int len=1;
if(i+1<s.length()&&(s.charAt(i+1)=='-'||s.charAt(i+1)=='=')) {
++len;
for(int k=i+2;k<s.length()&&s.charAt(k)==s.charAt(i+1);++k) {
++len;
}
}
result=Math.max(result,len);
}
else if(c=='>') {
int len=1;
if(i-1>=0&&(s.charAt(i-1)=='-'||s.charAt(i-1)=='=')) {
++len;
for(int k=i-2;k>=0&&s.charAt(k)==s.charAt(i-1);--k) {
++len;
}
}
result=Math.max(result,len);
}
}
return result;
}
}
problem2 link
把词建一个树,那么对于一个节点$u$,如果$u$不是一个单词,那么$f(u)=\prod _{v\in S_{u}}f(v)$,否则$f(u)=1+\prod _{v\in S_{u}}f(v)$.$S_{u}$表示$u$的孩子集合。
import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class PrefixFreeSubsets { static class Tree {
public boolean end;
Tree[] sons=null; public Tree() {
end=false;
sons=new Tree[26];
} } static Tree head=null; public long cantPrefFreeSubsets(String[] words) {
head=new Tree();
for(String s:words) {
Tree cur=head;
for(int i=0;i<s.length();++i) {
int t=s.charAt(i)-'a';
if(cur.sons[t]==null) {
cur.sons[t]=new Tree();
}
cur=cur.sons[t];
}
cur.end=true;
}
return dfs(head);
} static long dfs(Tree cur) {
long result=1,num=0;
for(int i=0;i<26;++i) {
if(cur.sons[i]==null) {
continue;
}
result*=dfs(cur.sons[i]);
++num;
}
if(num==0) {
return 2;
}
if(cur.end) {
++result;
}
return result;
}
}
problem3 link
设$f[i]=1$ 表示先手赢,$f[i]=0$ 表示后手赢。由于每次拿的石子数范围是$[1,22]$,所以如果出现两个位置$p,q$,使得$f[p],f[p+1],..,f[p+21]$与$f[q],f[q+1],..,f[q+21]$完全相等,那么就形成一个循环。所以只需要暴力找到这个循环位置即可。
import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class LongLongNim { static boolean[] f=new boolean[1<<22];
static int[] g=new int[1<<22]; public int numberOfWins(int maxN,int[] moves) {
Arrays.fill(f,false);
Arrays.fill(g,-1);
f[0]=false;
int pre=0;
int start0=-1,start1=-1;
for(int i=1;i<=maxN;++i) {
boolean ok=false;
for(int j=0;j<moves.length&&i>=moves[j];++j) {
if(!f[i-moves[j]]) {
ok=true;
break;
}
}
f[i]=ok;
if(f[i]) {
pre=pre<<1|1;
}
else {
pre=pre<<1;
}
if(i>22&&(pre&(1<<22))!=0) {
pre^=1<<22;
}
if(i<22) {
continue;
}
if(g[pre]==-1) {
g[pre]=i-21;
}
else if(i-21-g[pre]>=22){
start0=g[pre];
start1=i-21;
break;
}
}
if(start0==-1) {
int result=0;
for(int i=1;i<=maxN;++i) {
if(!f[i]) {
++result;
}
}
return result;
}
int result0=0,result1=0;
for(int i=1;i<start0;++i) {
if(!f[i]) {
++result0;
}
}
for(int i=start0;i<start1;++i) {
if(!f[i]) {
++result1;
}
}
maxN-=start0-1;
result1*=maxN/(start1-start0);
maxN%=start1-start0;
for(int i=0;i<maxN;++i) {
if(!f[start0+i]) {
++result1;
}
}
result1+=result0;
return result1;
}
}