次方数前缀和公式推导
之前训练赛上碰到了这么一道题:Problem - E - Codeforces
要求 \(\sum_{i=1}^n i^5\ (n~is~so~big)\)??,一般只会记平方数,立方数前缀和公式。这俩我都经常记不住
好在之前学过如果通过低次的次方数前缀和推到高次,但写这题的时候忘了,又滚去百度了一波。
为了加深记忆,写个博客记录下到底是怎么推的。
已知 \(\sum_{i=1}^n i=\dfrac {n*(n+1)}2\)??,求 \(\sum_{i=1}^n i^2\)??:
\[\sum_{i=1}^n (i+1)^3=\sum_{i=1}^n (i^3+3i^2+3i+1)\\ (n+1)^3-1=3\sum_{i=1}^n i^2+3\sum_{i=1}^n i^2+n\\ \sum_{i=1}^n i^2=\frac {(n+1)^3-n-1}{3}-\frac{n(n+1)}{2}=\frac {n(n+1)(n+2)}{6} \]同理,要求立方数的前缀和公式,则对 \(\sum_{i=1}^n (i+1)^4\)?? 进行同样的操作,同时我们也可从中得出一个结论:\(n\) 次方数的前缀和公式一定是个 \(n+1\) 次多项式。
这样推在高次的时候会挺麻烦的,可能要在草稿纸上算挺久化简化一年,但确实简单易懂,好想好记。
而且如果时间复杂度允许的话,也不用特意花大量时间去计算式子并化简、然后套公式 \(O(1)\)?? 求解;只需在草稿纸上根据二项式定理多展开几项,然后写好对应的函数 calx(n)
计算\(\sum_{i=1}^n i^x\)??,类似递归地调用一下即可,时间复杂度也是常数级的。
比如要求 \(i^7\)????????????????? 次方,那我们把 \(i^{4+1}\sim i^{7+1}\)????????????????? 都展开一下,然后 ??cal7(n)
调用 cal6(n)
调用 cal5(n)
。。。一直到 cal3(n)
(一般立方数的前缀和我们知道)递归结束假递归,每个函数都不一样。
感觉可能还有更好的方法来求解次方数前缀和问题?但私以为这个就够用了,于是就懒得去找了,总之先放这儿,以后如果学到了啥更优秀的方法再回头更新一波估计是莫得了。
顺便贴一下该题的代码,二分 + Java 处理大数。训练时写的,贼丑,慎看
import java.math.BigInteger;
import java.util.Scanner;
class Main {
static BigInteger cal(BigInteger x){
BigInteger x2=x.multiply(x);
BigInteger x1=x.add(BigInteger.ONE);
x1=x1.multiply(x1);
BigInteger ret=x2.multiply(x1);
// System.out.println(ret);
x=x.multiply(BigInteger.valueOf(2));
x2=x2.add(x2);
ret=ret.multiply(x.add(x2).subtract(BigInteger.ONE));
ret=ret.divide(BigInteger.valueOf(12));
return ret;
}
public static void main(String[] args) {
String P=new String();
String Q=new String();
Scanner in =new Scanner(System.in);
P=in.next();
Q=in.next();
BigInteger p=new BigInteger(P);
BigInteger q=new BigInteger(Q);
// System.out.println(p.divide(q));
BigInteger x=BigInteger.ZERO;
BigInteger ans=BigInteger.ZERO;
BigInteger d=BigInteger.ONE;
for(long i=1;;i++){
BigInteger ti=BigInteger.valueOf(i).pow(5);
BigInteger tx=ti.multiply(q);
if(tx.compareTo(p)>=0){
d=BigInteger.valueOf(i);
ans=tx;
break;
}
x=x.add(tx);
x=x.subtract(p);
// x=x.add(tx);
// x=x.subtract(p);
// if(x.multiply(BigInteger.valueOf(-1)).compareTo(p)>=0||tx.compareTo(p)>=0){
// d=BigInteger.valueOf(i);
// ans=tx;
// break;
// }
}
// System.out.println("x = "+x);
// System.out.println("d = "+ d);
x=p.subtract(x);
System.out.println(x);
// System.out.println(d);
// System.out.println(cal(d));
BigInteger dt=cal(d);
BigInteger mb=new BigInteger("1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
mb=mb.subtract(ans);
BigInteger l=d.add(BigInteger.ONE);
BigInteger r=new BigInteger("100000000000000000000");
BigInteger y=l;
while(l.compareTo(r)<=0){
BigInteger mid=l.add(r).divide(BigInteger.valueOf(2));
// System.out.println("mid = "+mid);
BigInteger t=cal(mid).subtract(dt);
t=t.multiply(q);
BigInteger cj=mid.subtract(d);
t=t.subtract(cj.multiply(p));
if(t.compareTo(mb)>=0){
y=mid;
r=mid.subtract(BigInteger.ONE);
}
else {
l=mid.add(BigInteger.ONE);
}
}
System.out.println(y);
}
}