差分序列
不小心遇到一题4次求和,推公式推了好久。。想想实在是没有必要,每次遇到还得推一边实在是累。。所以,回来就写了一个差分的版本,单次计算的效率不比直接公式差,不容易出错,而且,再也不用蛋去推多项式公式了
至于什么是差分序列,这个我就不解释了,wiki上应该可以找到。我的写法是借鉴了牛顿插值的,使用了一个递推的写法(一般求多项式都会用这个, 比如4n^3 + n^2 + 2 * n + 3,一般写成 ((4n + 1) * n + 2) * n + 3)
初始化细节说明:order是生成的多项式的阶,请确保它大于或等于实际的多项式阶。order阶的多项式需要用order+1项进行init,请把这前order+1项存入数组cof中。最后调用init函数,就可以用calc来计算任意项了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | /****************************************************************************** * Differential Sequence * init: O(order^2) * you should init the cof[i] with the value of i-th value of sequence * the sequene start from startfrom, default is 0, so a[0] is the first one * of sequence a * calc: O(order) ****************************************************************************/ const int ORDERLIM = 100; double cof[ORDERLIM + 1]; int order; const int startfrom = 0; void init() { int i, j; for(i = 1; i <= order; i++) { for(j = order; j >= i; j--) { cof[j] -= cof[j - 1]; } } } double calc(double n) { int i; double res = 0; for(i = order; i > 0; i--) { res += cof[i]; res *= (n - i + 1 - startfrom) / i; } res += cof[i]; return res; } /****************************************************************************** * MOD version of Differential Sequence * cof should not overflow MOD * MOD should should not less than order * MOD should be prime * need inverse in mod MOD system ****************************************************************************/ typec MOD = 1000000007; typec cof[ORDERLIM + 1]; typec inv[ORDERLIM + 1]; int order; const int startfrom = 0; void init() { int i, j; for(i = 1; i <= order; i++) { inv[i] = inverse(i, MOD); for(j = order; j >= i; j--) { cof[j] -= cof[j - 1]; } } } typec calc(typec n) { int i; typec res = 0; for(i = order; i > 0; i--) { res += cof[i], res %= MOD; res *= (n - i + 1 - startfrom) % MOD * inv[i] % MOD; res %= MOD; } res += cof[i], res %= MOD; while(res < 0) res += MOD; return res; } |

