算法刷题2

游戏

相当于玩石子游戏,一人拿后另外一人再拿
博弈论
基本玩法

①1066
n:石子数 k:最多拿多少个

if(n%(k+1)==0){
            后手胜
        }else{
            前手胜
        }

②1067
共有N个石子,每次每人拿K1,K2,K3…KN个
(策略)
博弈论的关键: 局面逆转, 如果能把当前局面逆转为必输局面, 先手就获胜. (让对手面临必输局面)

写的过程中我们发现, 石子数为N时, 输赢和N-1, N-3, N-4有关. 如果N-1, N-3, N-3存在必输局面, 先手获胜.

进一步观察, 发现存在循环.
即n%7==0||n%7==2后手胜
③1072
威佐夫博弈(Wythoff Game):
有两堆各若干的物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同件物品,规定最后取完者胜利。
直接说结论了,若两堆物品的初始值为(x,y),且x小于y,则另z=y-x;
记w=(int)[((sqrt(5)+1)/2)*z ];
若w=x,则先手必败,否则先手必胜。
④Nim1069
结论就是:把每堆物品数全部异或起来,如果得到的值为0,那么先手必败,否则先手必胜。

1073约瑟夫环数学公式法

f(1) = 0
f(n) = (f(n-1)+k)%n (n>1)

1079 中国剩余定理

算法的基本逻辑
1. 取一个p(质数),并计算所有质数的最小公倍数lcm,d=lcm/p(记作d)
2. 寻找d的倍数(记作x=i*d),使得x对p取模结果为1
3. 计算x与该p对应的m(余数)的乘积,记为y,即y=xm;
4. 对每一个p重复上述过程,将得到的所有y求和,对lcm取模,就是答案

1081子列和

那么到底什么是前缀和算法呢?
就以这道题为例,即为通过提前算好各前i项和,在后面查询时 能够大量减少计算量,避免重复计算,节省时间,不过需要注意相应的下标。
在这样一个静态数组中,前缀和更好,如果是在要动态修改的数组,那就使用线段数或树状数组更好

1088最长回文子列长度

  • 以中间为一点向两边扩散的对称
    1.当回文串为奇数,对比i+j和i-j是否相等即可
    2.当回文串为偶数,对比i+j以及i-j+1(去掉中间的点)

1089回文字符串manacher算法

1.解决长度奇偶性带来的对称轴位置问题
使得所有字符串都是奇数长度

aba  ———>  #a#b#a#
abba ———>  #a#b#b#a#

解决重复访问问题
RL数组:回文半径数组
RL-1即答案
问题转化如何求RL数组?

char:    # a # b # a #
 RL :    1 2 1 4 1 2 1
RL-1:    0 1 0 3 0 1 0
  i :    0 1 2 3 4 5 6

3.求RL数组
辅助变量:
MaxRight(前i个变量的回文字符串所能达到的最右边)
posMaxRight对应回文串的对称轴

假设当前访问到的位置为i,即要求RL[i],i必然是在po右边的(obviously)。但我们更关注的是,i是在MaxRight的左边还是右边。我们分情况来讨论。

manacher算法参考

1106 质数检测V2

BigInteger 有一个.isProblePrime(certainty)certainty越高准确率越高

1130斯特林近似求阶乘

原式子

代码化简

((long) (0.5 * Math.log10(2 * n * Math.PI) + n * Math.log10(n / Math.E) + 1));

你可能感兴趣的:(算法)