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:
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
2 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
Author: LIN, Xi
Source: The 2014 ACM-ICPC Asia Mudanjiang Regional First Round
解题思路:对于询问[L,R]只有2种情况:1.在一段中 2.L,R分别在两段中,中间有若干段
第一步:
那么我们先处理原串P的情况。
在纸上写一下,容易发现,G(l,r)只有奇数项
且G(l,r)=a[l]*(r-l+1)+a[l+2]*(r-l-1)+....=sigma(a[x]*(r-x+1))=(r+1)*sigma(a[x])-sigma(a[x]*x)
那么,我们用树状数组维护a[x]和a[x]*x两个前缀和,修改就是单点修改。
但是,偶数项和并不是不用了,如果前面有一段是奇数,后面就要用到偶数项和
所以要维护奇数偶数项前缀的4个数组。
第二步:
我们已经知道原串P的任意一个区间的答案
如果有2个P长度的串,且P的长度为奇数,那么整个区间的答案就应该是第一个P的奇数项前缀和+第二个P的偶数项前缀和+第一个P的奇数项的偏移量(奇数项和*P)
我们在处理P的时候,就计算2*P长度的前缀和,这样对于中间的段都是以2*P分段的
我们设[L,R]被分成[ml,len],n个2*P,1或0个P,[1,mr]这几段,ml,mr为段内下标
[ml,len]的部分很好算就是原来的值加上偏移量
然后[1,mr]部分就是原来的值
设k为中间P的段数
n个2*P的部分为原来n个2*P的前缀和+偏移量
偏移量是2*P的前缀和(奇数项还是偶数项要看[L,len]的奇偶)*{sigma((k-2*b)*len+mr) ,b属于[1,n]}
如果还有剩下的P,再加上P的值和偏移量
第三步:
额,没了
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 100010
#define ll long long
#define mod 1000000007
using namespace std;
int t,ls;
char s[maxn];
int v[maxn<<1];
ll a[2][maxn<<1],b[2][maxn<<1];
void add(int t,int c,int d){
for(int x=c;x<=2*ls;x+=x&(-x)){
a[t][x]+=c*d,b[t][x]+=d;
a[t][x]%=mod,b[t][x]%=mod;
}
}
ll ask(ll *c,int x){
ll ret=0;
for(;x;x-=x&(-x)) ret+=c[x],ret%=mod;
return ret;
}
void read(){
scanf("%s",s+1);
ls=strlen(s+1);
for(int i=1;i<=ls;i++) v[i]=s[i]-'0';
for(int i=ls+1;i<=2*ls;i++) v[i]=v[i-ls];
memset(a,0,sizeof a);
memset(b,0,sizeof b);
for(int i=1;i<=2*ls;i++) add(i&1,i,v[i]);
}
ll calc(int t,ll ml,ll mr){
ll ret=((mr+1)*(ask(b[t],mr)-ask(b[t],ml-1)))%mod-(ask(a[t],mr)-ask(a[t],ml-1))%mod;
return ret%mod;
}
void solve(){
int q,T,x,d;
ll l,r;
scanf("%d",&q);
for(int i=0;i<q;i++){
scanf("%d",&T);
if(T==1){
scanf("%d%d",&x,&d);
add(x&1,x,-v[x]);
add(x&1,x,d);
add((x+ls)&1,x+ls,-v[x]);
add((x+ls)&1,x+ls,d);
v[x]=d;
}else{
scanf("%lld%lld",&l,&r);
ll kl=(l+ls-1)/ls,kr=(r+ls-1)/ls;
ll ml=l-(kl-1)*ls,mr=r-(kr-1)*ls;
ll ret=0;
ll kk=kr-kl-1,rr,sum;
if(kl==kr){
ret=calc(ml&1,ml,mr);
}else{
ret=calc(ml&1,ml,ls);
ret=(ret+(ask(b[ml&1],ls)-ask(b[ml&1],ml-1))*(ls*(kk%mod)%mod+mr)%mod)%mod;
sum=ask(b[1^((ls-ml+1)&1)],2*ls);
ll bb=kk/2;
if(bb>=1){
bb%=mod;
ret=(ret+calc(1^((ls-ml+1)&1),1,2*ls)*bb%mod)%mod;
ret=(ret+sum*( (mr+kk%mod*ls%mod)*bb%mod-bb*(bb+1)%mod*ls%mod )%mod)%mod;
}
if(kk&1){
ret=(ret+calc(1^((ls-ml+1)&1),1,ls))%mod;
ret=(ret+ask(b[1^((ls-ml+1)&1)],ls)*mr%mod)%mod;
}
rr=ls-ml+1+ls*kk;
ret=(ret+calc(1^(rr&1),1,mr))%mod;
}
ret=(ret%mod+mod)%mod;
printf("%lld\n",ret);
}
}
}
int main(){
scanf("%d",&t);
for(int ca=1;ca<=t;ca++){
read();
solve();
}
return 0;
}