题目

July 6, 2021 · View on GitHub

There is a digit string S with infinite length. In addition, S is periodic and it can be formed by concatenating infinite repetitions of a base string P. For example, if P = 3423537, then S = 3423537342353734235373423537...

Let's define the alternating sum on substrings of S. Assume Sl..r is a substring of S from index l to index r (all indexes are 1-based), then the alternating sum of Sl..r is:

G(l, r) = Sl - Sl+1 + Sl+2 - ... + (-1)r-lSr

For example, S2..10 = 423537342, then G(2, 10) = 4 - 2 + 3 - 5 + 3 - 7 + 3 - 4 + 2 = -3.

Now, you are given the base string P and you have to do many operations. There are only two kinds of operations:

1 x d: set Px to d, d is a single digit.
2 l r: find the sum of G(i, j) that l <= i <= j <= r.

For each second operation, you should output the sum modulo 109 + 7.

Input
There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains a digit string P (1 <= length(P) <= 100000).

The second line contains an integer Q (1 <= Q <= 100000) indicating the number of operations. Each of the following Q lines is an operation in such format:

1 x d (1 <= x <= length(P), 0 <= d <= 9)
2 l r (1 <= l <= r <= 1018)

Output
For each "2 l r" operation, output an integer, indicating the sum modulo 109 + 7.

Sample Input

324242
4
2 1 1
2 1 4
1 3 7
2 3 4
324242
6
2 1 1
1 3 7
2 2 4
1 3 4
2 7 10
2 1 30

Sample Output

3
20
14
3
8
20
870

参考答案

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#define maxn 200010
#define mid ((t[p].l+t[p].r)>>1)
#define ls (p<<1)
#define rs (ls|1)
#define ll long long
#define mod 1000000007
using namespace std;
char st[maxn];
struct tree
{
    ll l,r;
    ll sum[2],tsum[2];
}t[maxn<<2];
void pushup(int p)
{
    ll l=t[ls].r-t[ls].l+1;
    ll r=t[rs].r-t[rs].l+1;
    if(l%2)
    {
        t[p].sum[0]=(t[ls].sum[0]+t[rs].sum[1])%mod;
        t[p].sum[1]=(t[ls].sum[1]+t[rs].sum[0])%mod;
        t[p].tsum[0]=(t[ls].tsum[0]+r*t[ls].sum[0]%mod+t[rs].tsum[1])%mod;
        t[p].tsum[1]=(t[ls].tsum[1]+r*t[ls].sum[1]%mod+t[rs].tsum[0])%mod;
    }
    else
    {
        t[p].sum[0]=(t[ls].sum[0]+t[rs].sum[0])%mod;
        t[p].sum[1]=(t[ls].sum[1]+t[rs].sum[1])%mod;
        t[p].tsum[0]=(t[ls].tsum[0]+r*t[ls].sum[0]%mod+t[rs].tsum[0])%mod;
        t[p].tsum[1]=(t[ls].tsum[1]+r*t[ls].sum[1]%mod+t[rs].tsum[1])%mod;
    }
}
void build(int p,int l,int r)
{
    t[p].l=l,t[p].r=r;
    t[p].sum[0]=t[p].sum[1]=t[p].tsum[0]=t[p].tsum[1]=0;
    if(l==r)
    {
        t[p].sum[0]=t[p].tsum[0]=0;
        t[p].sum[1]=t[p].tsum[1]=st[l]-'0';
        return;
    }
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(p);
}
void modify(int p,int po,ll d)
{
    if(t[p].l==t[p].r)
    {
        t[p].sum[1]=t[p].tsum[1]=d;
        return;
    }
    if(po>mid)
    modify(rs,po,d);
    else
    modify(ls,po,d);
    pushup(p);
}
tree query(int p,ll l,ll r)
{
    tree tmp;
    if(t[p].l==l&&t[p].r==r)
    {
        return t[p];
    }
    if(l>mid)
    return query(rs,l,r);
    else if(r<=mid)
    return query(ls,l,r);
    else
    {
        tree t1=query(ls,l,mid);
        tree t2=query(rs,mid+1,r);
        tmp.l=t1.l,tmp.r=t2.r;
        ll l=t1.r-t1.l+1;
        ll r=t2.r-t2.l+1;
        if(l%2){
            tmp.sum[0]=(t1.sum[0]+t2.sum[1])%mod;
            tmp.sum[1]=(t1.sum[1]+t2.sum[0])%mod;
            tmp.tsum[0]=(t1.tsum[0]+r*t1.sum[0]%mod+t2.tsum[1])%mod;
            tmp.tsum[1]=(t1.tsum[1]+r*t1.sum[1]%mod+t2.tsum[0])%mod;
        }
        else{
            tmp.sum[0]=(t1.sum[0]+t2.sum[0])%mod;
            tmp.sum[1]=(t1.sum[1]+t2.sum[1])%mod;
            tmp.tsum[0]=(t1.tsum[0]+r*t1.sum[0]%mod+t2.tsum[0])%mod;
            tmp.tsum[1]=(t1.tsum[1]+r*t1.sum[1]%mod+t2.tsum[1])%mod;
        }
        return tmp;
    }
}
ll getsum(ll num,ll len,ll left,int typ)
{
    if(num==0)
    return 0;
    ll sum=0;
    sum=num%mod*t[1].tsum[typ]%mod;
    ll tt;
    if(num%2)
    tt=((num-1)/2)%mod*(num%mod);
    else
    tt=((num-1)%mod)*((num/2)%mod);
    tt%=mod;
    ll tmp=(num%mod*left%mod+tt*len%mod)%mod;
    sum=(sum+tmp*t[1].sum[typ]%mod)%mod;
    return sum;
}
int main()
{
  // freopen("dd.txt","r",stdin);
    int ncase;
    scanf("%d",&ncase);
    while(ncase--)
    {
        scanf("%s",st);
        int len=strlen(st);
        for(int i=0;i<len;i++)
        {
            st[i+len]=st[i];
        }
        len*=2;
        build(1,0,len-1);
        int q;
        scanf("%d",&q);
        while(q--){
            int typ;
            ll ans=0,l,r;
            scanf("%d",&typ);
            if(typ==1)
            {
                int x,d;
                scanf("%d%d",&x,&d);
                modify(1,x-1,d);
                modify(1,x-1+(len/2),d);
            }
            else
            {
                scanf("%lld%lld",&l,&r);
                l--,r--;
                ll lpo=l/len,rpo=r/len;
                ll L=l%len,R=r%len;
                if(lpo==rpo)
                {
                    ans=query(1,L,R).tsum[1];
                }
                else
                {
                    ll Len=((r-l+1)-(len-L))%mod;
                    tree t1=query(1,L,len-1);
                    tree t2=query(1,0,R);
                    ans=(ans+t1.tsum[1]+Len*t1.sum[1]%mod)%mod;
                    if((len-L)%2)
                    ans=(ans+t2.tsum[0])%mod;
                    else
                    ans=(ans+t2.tsum[1])%mod;
                    if((len-L)%2)
                    ans=(ans+getsum(rpo-lpo-1,len,R+1,0))%mod;
                    else
                    ans=(ans+getsum(rpo-lpo-1,len,R+1,1))%mod;
                }
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}