[前缀积][后缀积][分块] Jzoj 100035 区间
题解
- 首先,将s数列构造出来
- 然后分块,每k个一块
- 可以预处理出块中前缀积和后缀积
- 如果当前刚好是一个块的话,直接将块中积异或ans
- 如果不是,就是区间分成上一个后缀积乘前缀积
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 using namespace std; 5 int n,k,mo,b,c,d,ans,s[20000010],k1[20000010],k2[20000010]; 6 int main() 7 { 8 freopen("range.in","r",stdin); 9 freopen("range.out","w",stdout); 10 scanf("%d%d%d",&n,&k,&mo); 11 scanf("%d%d%d%d",&s[1],&b,&c,&d); 12 for (int i=2;i<=n;i++) s[i]=(s[i-1]*1LL*b+c)%d; 13 int cnt=n/k; 14 for (int i=0;i<cnt;i++) 15 { 16 int w=i*k+1; 17 k1[w]=s[w]; 18 for (int j=w+1;j<w+k;j++) k1[j]=k1[j-1]*1LL*s[j]%mo; 19 k2[w+k-1]=s[w+k-1]; 20 for (int j=w+k-2;j>=w;j--) k2[j]=k2[j+1]*1LL*s[j]%mo; 21 } 22 if (n%k!=0) 23 { 24 int w=cnt*k+1; 25 k1[w]=s[w]; 26 for(int i=w+1;i<=n;i++) k1[i]=k1[i-1]*1LL*s[i]%mo; 27 k2[n]=s[n]; 28 for(int i=n-1;i>=w;i--) k2[i]=k2[i+1]*1LL*s[i]%mo; 29 } 30 for (int i=1;i<=n-k+1;i++) 31 if (i%k==1) ans=ans^k1[i+k-1]; 32 else ans=ans^k2[i]*1LL*k1[i+k-1]%mo; 33 printf("%d",ans); 34 return 0; 35 }