[树状数组]uva 5798 Jupiter Atacks!

来源:互联网 发布:淘宝诈骗报警能找回 编辑:程序博客网 时间:2024/05/16 12:58

H(fi,..., fj) = $\displaystyle \sum_{{k=0}}^{{j-i}}$Bkfj-k    ( mod P)


 
/**uva 5798 动态更新fi 的值,查询H(fi,...fj)写出f11,f12,...f15;f22,f23,,,f25;....以最长的f15 作参照, 设 a1...a5 分别为f15的第5....1项,sum 为a的和, 则 f(i,j) = (sum(j) - sum(i-1) ) / b^(n-j) % p求和用树状数组,模p用欧拉定理(题目关键2≤B <P≤109 and P prime)。trick:注意减法会产生负数*/#include <stdio.h>#include <string.h>#define N 100001#define lowbit(i) (i) & (-i)__int64 B[N],f[N],A[N];int n;void add(int i,__int64 c){    for(; i <= n;i += lowbit(i) )        A[i] += c;}__int64 sum(int i){    __int64 ans = 0LL;    for(; i > 0; i -= lowbit(i))        ans += A[i];    return ans;}__int64 fpow(__int64 a,__int64 b,__int64 p){    __int64 ans = 1LL;    while(b)    {        if(b&1)            ans = ans * a % p;        b >>= 1;        a = a * a % p;    }    return ans;}int main(){    B[0] = 1LL;    int q,i,j;    __int64 b,p;    char ask[4];    while(scanf("%I64d%I64d%d%d",&b,&p,&n,&q) != EOF && b)    {        memset(A,0,sizeof(A));        memset(f,0,sizeof(f));        for(i = 1; i < n; ++i)            B[i] = B[i-1] * b % p;        while(q--)        {            scanf("%s %d%d",ask,&i,&j);            if(ask[0] == 'H')            {                printf("%I64d\n",(sum(j)-sum(i-1) + p) % p * fpow(B[n-j],p-2,p) % p);                continue;            }            add(i,(1LL * j- f[i] + p) % p * B[n-i] % p);            f[i] = j;        }        puts("-");    }    return 0;}




原创粉丝点击